Skip to content

Commit d45cffd

Browse files
Merge pull request #22 from NativeScript/vladimirov/fix-getting-cli-version
Fix parsing of CLI's output
2 parents 8b2cfb6 + 9595b8d commit d45cffd

File tree

3 files changed

+92
-39
lines changed

3 files changed

+92
-39
lines changed

lib/sys-info.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class SysInfo implements NativeScriptDoctor.ISysInfo {
1717
private static JAVA_COMPILER_VERSION_REGEXP = /^javac (.*)/im;
1818
private static XCODE_VERSION_REGEXP = /Xcode (.*)/;
1919
private static VERSION_REGEXP = /(\d{1,})\.(\d{1,})\.*([\w-]{0,})/m;
20+
private static CLI_OUTPUT_VERSION_REGEXP = /^(?:\d+\.){2}\d+.*?$/m;
2021
private static GIT_VERSION_REGEXP = /^git version (.*)/;
2122
private static GRADLE_VERSION_REGEXP = /Gradle (.*)/i;
2223

@@ -298,14 +299,14 @@ export class SysInfo implements NativeScriptDoctor.ISysInfo {
298299
public getNativeScriptCliVersion(): Promise<string> {
299300
return this.getValueForProperty(() => this.nativeScriptCliVersionCache, async (): Promise<string> => {
300301
const output = await this.execCommand("tns --version");
301-
return output ? this.getVersionFromString(output.trim()) : output;
302+
return output ? this.getVersionFromCLIOutput(output.trim()) : output;
302303
});
303304
}
304305

305306
public getNativeScriptCloudVersion(): Promise<string> {
306307
return this.getValueForProperty(() => this.nativeScriptCloudVersionCache, async (): Promise<string> => {
307308
const output = await this.execCommand("tns cloud lib version");
308-
return output ? this.getVersionFromString(output.trim()) : output;
309+
return output ? this.getVersionFromCLIOutput(output.trim()) : output;
309310
});
310311
}
311312

@@ -442,6 +443,11 @@ export class SysInfo implements NativeScriptDoctor.ISysInfo {
442443
return null;
443444
}
444445

446+
private getVersionFromCLIOutput(commandOutput: string): string {
447+
const matches = commandOutput.match(SysInfo.CLI_OUTPUT_VERSION_REGEXP);
448+
return matches && matches[0];
449+
}
450+
445451
private async winVer(): Promise<string> {
446452
let productName: string;
447453
let currentVersion: string;

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nativescript-doctor",
3-
"version": "0.5.1",
3+
"version": "0.5.2",
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",

test/sys-info.ts

+83-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as assert from "assert";
22
import * as path from "path";
3+
import { EOL } from "os";
34
import { SysInfo } from "../lib/sys-info";
45
import { Helpers } from "../lib/helpers";
56
import { ChildProcess } from "../lib/wrappers/child-process";
@@ -14,7 +15,13 @@ interface IChildProcessResultDescription {
1415
shouldThrowError?: boolean;
1516
}
1617

18+
interface ICLIOutputVersionTestCase {
19+
testedProperty: string;
20+
method: (sysInfo: SysInfo) => Promise<string>;
21+
}
22+
1723
interface IChildProcessResults {
24+
[property: string]: IChildProcessResultDescription;
1825
uname: IChildProcessResultDescription;
1926
npmV: IChildProcessResultDescription;
2027
nodeV: IChildProcessResultDescription;
@@ -30,6 +37,7 @@ interface IChildProcessResults {
3037
podVersion: IChildProcessResultDescription;
3138
pod: IChildProcessResultDescription;
3239
nativeScriptCliVersion: IChildProcessResultDescription;
40+
nativeScriptCloudVersion: IChildProcessResultDescription;
3341
git: IChildProcessResultDescription;
3442
}
3543

@@ -86,6 +94,7 @@ function createChildProcessResults(childProcessResult: IChildProcessResults): ID
8694
'"C:\\Program Files/Git/cmd/git.exe" --version': childProcessResult.gitVersion, // When running Windows test on the Non-Windows platform
8795
"gradle -v": childProcessResult.gradleVersion,
8896
"tns --version": childProcessResult.nativeScriptCliVersion,
97+
"tns cloud lib version": childProcessResult.nativeScriptCloudVersion,
8998
"emulator": { shouldThrowError: false },
9099
"which git": childProcessResult.git
91100
};
@@ -150,6 +159,7 @@ function setStdErr(value: string): { stderr: string } {
150159

151160
describe("SysInfo unit tests", () => {
152161
let sysInfo: SysInfo;
162+
const dotNetVersion = "4.5.1";
153163

154164
beforeEach(() => {
155165
// We need to mock this because on Mac the tests in which the platform is mocked to Windows in the process there will be no CommonProgramFiles.
@@ -230,6 +240,7 @@ describe("SysInfo unit tests", () => {
230240
podVersion: { result: setStdOut("0.38.2") },
231241
pod: { result: setStdOut("success") },
232242
nativeScriptCliVersion: { result: setStdOut("2.5.0") },
243+
nativeScriptCloudVersion: { result: setStdOut("0.1.0") },
233244
git: { result: setStdOut("git") }
234245
};
235246

@@ -264,25 +275,25 @@ describe("SysInfo unit tests", () => {
264275
it("on Windows", async () => {
265276
const originalProgramFiles = process.env[PROGRAM_FILES];
266277
process.env[PROGRAM_FILES] = PROGRAM_FILES_ENV_PATH;
267-
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion: "4.5.1" });
268-
let result = await sysInfo.getSysInfo();
278+
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion });
279+
const result = await sysInfo.getSysInfo();
269280
process.env[PROGRAM_FILES] = originalProgramFiles;
270281
assertCommonValues(result);
271282
assert.deepEqual(result.xcodeVer, null);
272283
assert.deepEqual(result.cocoaPodsVer, null);
273284
});
274285

275286
it("on Mac", async () => {
276-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
277-
let result = await sysInfo.getSysInfo();
287+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
288+
const result = await sysInfo.getSysInfo();
278289
assertCommonValues(result);
279290
assert.deepEqual(result.xcodeVer, "6.4.0");
280291
assert.deepEqual(result.cocoaPodsVer, childProcessResult.podVersion.result.stdout);
281292
});
282293

283294
it("on Linux", async () => {
284-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: false, dotNetVersion: "4.5.1" });
285-
let result = await sysInfo.getSysInfo();
295+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: false, dotNetVersion });
296+
const result = await sysInfo.getSysInfo();
286297
assertCommonValues(result);
287298
assert.deepEqual(result.xcodeVer, null);
288299
assert.deepEqual(result.cocoaPodsVer, null);
@@ -293,55 +304,90 @@ describe("SysInfo unit tests", () => {
293304
it("is null when cocoapods are not installed", async () => {
294305
// simulate error when pod --version command is executed
295306
childProcessResult.podVersion = { shouldThrowError: true };
296-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
297-
let result = await sysInfo.getSysInfo();
307+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
308+
const result = await sysInfo.getSysInfo();
298309
assert.deepEqual(result.cocoaPodsVer, null);
299310
});
300311

301312
it("is null when OS is not Mac", async () => {
302313
const originalProgramFiles = process.env[PROGRAM_FILES];
303314
process.env[PROGRAM_FILES] = PROGRAM_FILES_ENV_PATH;
304-
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion: "4.5.1" });
305-
let result = await sysInfo.getSysInfo();
315+
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion });
316+
const result = await sysInfo.getSysInfo();
306317
process.env[PROGRAM_FILES] = originalProgramFiles;
307318
assert.deepEqual(result.cocoaPodsVer, null);
308319
});
309320

310321
it("is correct when cocoapods output has warning after version output", async () => {
311322
childProcessResult.podVersion = { result: setStdOut("0.38.2\nWARNING:\n") };
312-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
313-
let result = await sysInfo.getSysInfo();
323+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
324+
const result = await sysInfo.getSysInfo();
314325
assert.deepEqual(result.cocoaPodsVer, "0.38.2");
315326
});
316327

317328
it("is correct when cocoapods output has warnings before version output", async () => {
318329
childProcessResult.podVersion = { result: setStdOut("WARNING\nWARNING2\n0.38.2") };
319-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
320-
let result = await sysInfo.getSysInfo();
330+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
331+
const result = await sysInfo.getSysInfo();
321332
assert.deepEqual(result.cocoaPodsVer, "0.38.2");
322333
});
323334
});
324335

325-
describe("nativeScriptCliVersion", () => {
326-
it("is null when tns is not installed", async () => {
327-
childProcessResult.nativeScriptCliVersion = { shouldThrowError: true };
328-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
329-
let result = await sysInfo.getSysInfo();
330-
assert.deepEqual(result.nativeScriptCliVersion, null);
331-
});
336+
const testData: ICLIOutputVersionTestCase[] = [
337+
{
338+
testedProperty: "nativeScriptCliVersion",
339+
method: (currentSysInfo: SysInfo) => currentSysInfo.getNativeScriptCliVersion()
340+
},
341+
{
342+
testedProperty: "nativeScriptCloudVersion",
343+
method: (currentSysInfo: SysInfo) => currentSysInfo.getNativeScriptCloudVersion()
344+
}];
345+
346+
testData.forEach((testCase) => {
347+
describe(testCase.testedProperty, () => {
348+
it("is null when tns is not installed", async () => {
349+
childProcessResult[testCase.testedProperty] = { shouldThrowError: true };
350+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
351+
const result = await testCase.method(sysInfo);
352+
assert.deepEqual(result, null);
353+
});
332354

333-
it("is correct when the version is the only row in `tns --version` output", async () => {
334-
childProcessResult.nativeScriptCliVersion = { result: setStdOut("3.0.0") };
335-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
336-
let result = await sysInfo.getSysInfo();
337-
assert.deepEqual(result.nativeScriptCliVersion, "3.0.0");
338-
});
355+
it("is correct when the version is the only row in command output", async () => {
356+
childProcessResult[testCase.testedProperty] = { result: setStdOut("3.0.0") };
357+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
358+
const result = await testCase.method(sysInfo);
359+
assert.deepEqual(result, "3.0.0");
360+
});
339361

340-
it("is correct when there are warnings in the `tns --version` output", async () => {
341-
childProcessResult.nativeScriptCliVersion = { result: setStdOut("Some warning due to invalid extensions\\n3.0.0") };
342-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
343-
let result = await sysInfo.getSysInfo();
344-
assert.deepEqual(result.nativeScriptCliVersion, "3.0.0");
362+
it("is correct when there are warnings in the command's output", async () => {
363+
childProcessResult[testCase.testedProperty] = { result: setStdOut(`Some warning due to invalid extensions${EOL}3.0.0`) };
364+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
365+
const result = await testCase.method(sysInfo);
366+
assert.deepEqual(result, "3.0.0");
367+
});
368+
369+
it("is correct when there are warnings with version in them in the command's output", async () => {
370+
const cliOutput = `
371+
Support for Node.js 7.6.0 is not verified. This CLI might not install or run properly.
372+
373+
3.0.0`;
374+
childProcessResult[testCase.testedProperty] = { result: setStdOut(cliOutput) };
375+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
376+
const result = await testCase.method(sysInfo);
377+
assert.deepEqual(result, "3.0.0");
378+
});
379+
380+
it("is correct when there are warnings in the command's output and searched version is a prerelease", async () => {
381+
const expectedCliVersion = "3.2.0-2017-07-21-9480";
382+
const cliOutput = `
383+
Support for Node.js 7.6.0 is not verified. This CLI might not install or run properly.
384+
385+
${expectedCliVersion}`;
386+
childProcessResult[testCase.testedProperty] = { result: setStdOut(cliOutput) };
387+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
388+
const result = await testCase.method(sysInfo);
389+
assert.deepEqual(result, expectedCliVersion);
390+
});
345391
});
346392
});
347393

@@ -363,14 +409,15 @@ describe("SysInfo unit tests", () => {
363409
podVersion: { shouldThrowError: true },
364410
pod: { shouldThrowError: true },
365411
nativeScriptCliVersion: { shouldThrowError: true },
412+
nativeScriptCloudVersion: { shouldThrowError: true },
366413
git: { shouldThrowError: false }
367414
};
368415
androidToolsInfo.validateAndroidHomeEnvVariable = (): any[] => [1];
369416
});
370417

371418
describe("when all of calls throw", () => {
372419
let assertAllValuesAreNull = async () => {
373-
let result = await sysInfo.getSysInfo();
420+
const result = await sysInfo.getSysInfo();
374421
assert.deepEqual(result.npmVer, null);
375422
assert.deepEqual(result.javaVer, null);
376423
assert.deepEqual(result.javacVersion, null);
@@ -387,18 +434,18 @@ describe("SysInfo unit tests", () => {
387434
it("on Windows", async () => {
388435
const originalProgramFiles = process.env[PROGRAM_FILES];
389436
process.env[PROGRAM_FILES] = PROGRAM_FILES_ENV_PATH;
390-
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion: "4.5.1" });
437+
sysInfo = mockSysInfo(childProcessResult, { isWindows: true, isDarwin: false, dotNetVersion });
391438
process.env[PROGRAM_FILES] = originalProgramFiles;
392439
await assertAllValuesAreNull();
393440
});
394441

395442
it("on Mac", async () => {
396-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion: "4.5.1" });
443+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: true, dotNetVersion });
397444
await assertAllValuesAreNull();
398445
});
399446

400447
it("on Linux", async () => {
401-
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: false, dotNetVersion: "4.5.1" });
448+
sysInfo = mockSysInfo(childProcessResult, { isWindows: false, isDarwin: false, dotNetVersion });
402449
await assertAllValuesAreNull();
403450
});
404451
});

0 commit comments

Comments
 (0)