Skip to content

Commit 74e5074

Browse files
author
Dimitar Tachev
authored
Merge pull request #5212 from NativeScript/release
chore: merge release into master
2 parents c71fbf9 + 6232003 commit 74e5074

File tree

5 files changed

+47
-17
lines changed

5 files changed

+47
-17
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
NativeScript CLI Changelog
22
================
33

4+
6.3.3 (2020, January 13)
5+
===
6+
7+
### New
8+
9+
* [Implemented #5205](https://github.com/NativeScript/nativescript-cli/issues/5205): Support build hooks
10+
* [Implemented #5210](https://github.com/NativeScript/nativescript-cli/issues/5210): Support environment check hooks
11+
12+
### Fixed
13+
14+
* [Fixed #3818](https://github.com/NativeScript/nativescript-cli/issues/3818): Cannot set property 'socket' of null
15+
16+
417
6.3.2 (2020, January 9)
518
===
619

lib/services/livesync/android-livesync-tool.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
7575
abstractPort: `localabstract:${configuration.appIdentifier}-livesync`
7676
});
7777

78-
const connectionResult = await this.connectEventuallyUntilTimeout(this.createSocket.bind(this, port), connectTimeout);
78+
const connectionResult = await this.connectEventuallyUntilTimeout(this.createSocket.bind(this, port), connectTimeout, configuration);
7979
this.handleConnection(connectionResult);
8080
}
8181

@@ -299,19 +299,33 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool {
299299
});
300300
}
301301

302-
private connectEventuallyUntilTimeout(factory: () => ILiveSyncSocket, timeout: number): Promise<{ socket: ILiveSyncSocket, data: Buffer | string }> {
302+
private connectEventuallyUntilTimeout(factory: () => ILiveSyncSocket, timeout: number, configuration: IAndroidLivesyncToolConfiguration): Promise<{ socket: ILiveSyncSocket, data: Buffer | string }> {
303303
return new Promise((resolve, reject) => {
304304
let lastKnownError: Error | string,
305305
isConnected = false;
306306

307-
const connectionTimer = setTimeout(() => {
307+
const connectionTimer = setTimeout(async () => {
308308
if (!isConnected) {
309309
isConnected = true;
310310
if (this.pendingConnectionData && this.pendingConnectionData.socketTimer) {
311311
clearTimeout(this.pendingConnectionData.socketTimer);
312312
}
313313

314-
reject(lastKnownError || new Error(AndroidLivesyncTool.SOCKET_CONNECTION_TIMED_OUT_ERROR));
314+
const applicationPid = await this.$androidProcessService.getAppProcessId(configuration.deviceIdentifier, configuration.appIdentifier);
315+
if (!applicationPid) {
316+
this.$logger.trace("In Android LiveSync tool, lastKnownError is: ", lastKnownError);
317+
this.$logger.info(`Application ${configuration.appIdentifier} is not running on device ${configuration.deviceIdentifier}.`.yellow);
318+
this.$logger.info(
319+
`This issue may be caused by:
320+
* crash at startup (try \`tns debug android --debug-brk\` to check why it crashes)
321+
* different application identifier in your package.json and in your gradle files (check your identifier in \`package.json\` and in all *.gradle files in your App_Resources directory)
322+
* device is locked
323+
* manual closing of the application`.cyan);
324+
reject(new Error(`Application ${configuration.appIdentifier} is not running`));
325+
} else {
326+
reject(lastKnownError || new Error(AndroidLivesyncTool.SOCKET_CONNECTION_TIMED_OUT_ERROR));
327+
}
328+
315329
this.pendingConnectionData = null;
316330
}
317331
}, timeout);

lib/services/platform-environment-requirements.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NATIVESCRIPT_CLOUD_EXTENSION_NAME, TrackActionNames } from "../constants";
2-
import { isInteractive } from "../common/helpers";
2+
import { isInteractive, hook } from "../common/helpers";
33
import { EOL } from "os";
44

55
export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequirements {
@@ -39,6 +39,7 @@ export class PlatformEnvironmentRequirements implements IPlatformEnvironmentRequ
3939
"deploy": "tns cloud deploy"
4040
};
4141

42+
@hook("checkEnvironment")
4243
public async checkEnvironmentRequirements(input: ICheckEnvironmentRequirementsInput): Promise<ICheckEnvironmentRequirementsOutput> {
4344
const { platform, projectDir, runtimeVersion } = input;
4445
const notConfiguredEnvOptions = input.notConfiguredEnvOptions || {};

test/services/livesync/android-livesync-tool.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ const createTestInjector = (socket: INetSocket, fileStreams: IDictionary<NodeJS.
7070
testInjector.register("injector", testInjector);
7171
testInjector.register("mobileHelper", MobileHelper);
7272
testInjector.register("androidProcessService", {
73-
forwardFreeTcpToAbstractPort: () => Promise.resolve("")
73+
forwardFreeTcpToAbstractPort: () => Promise.resolve(""),
74+
getAppProcessId: () => Promise.resolve("1234")
7475
});
7576
testInjector.register("LiveSyncSocket", () => socket);
7677
testInjector.register("devicePlatformsConstants", DevicePlatformsConstants);

test/services/platform-environment-requirements.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ function createTestInjector() {
1818
testInjector.register("analyticsService", {
1919
trackEventActionInGoogleAnalytics: () => ({})
2020
});
21-
testInjector.register("commandsService", {currentCommandData: {commandName: "test", commandArguments: [""]}});
21+
testInjector.register("commandsService", { currentCommandData: { commandName: "test", commandArguments: [""] } });
2222
testInjector.register("doctorService", {});
23+
testInjector.register("hooksService", stubs.HooksServiceStub);
2324
testInjector.register("errors", {
2425
fail: (err: any) => {
2526
throw new Error(err.formatStr || err.message || err);
@@ -47,21 +48,21 @@ describe("platformEnvironmentRequirements ", () => {
4748
describe("checkRequirements", () => {
4849
let testInjector: IInjector = null;
4950
let platformEnvironmentRequirements: IPlatformEnvironmentRequirements = null;
50-
let promptForChoiceData: {message: string, choices: string[]}[] = [];
51+
let promptForChoiceData: { message: string, choices: string[] }[] = [];
5152
let isExtensionInstallCalled = false;
5253

53-
function mockDoctorService(data: {canExecuteLocalBuild: boolean, mockSetupScript?: boolean}) {
54+
function mockDoctorService(data: { canExecuteLocalBuild: boolean, mockSetupScript?: boolean }) {
5455
const doctorService = testInjector.resolve("doctorService");
5556
doctorService.canExecuteLocalBuild = () => data.canExecuteLocalBuild;
5657
if (data.mockSetupScript) {
5758
doctorService.runSetupScript = () => Promise.resolve();
5859
}
5960
}
6061

61-
function mockPrompter(data: {firstCallOptionName: string, secondCallOptionName?: string}) {
62+
function mockPrompter(data: { firstCallOptionName: string, secondCallOptionName?: string }) {
6263
const prompter = testInjector.resolve("prompter");
6364
prompter.promptForChoice = (message: string, choices: string[]) => {
64-
promptForChoiceData.push({message: message, choices: choices});
65+
promptForChoiceData.push({ message: message, choices: choices });
6566

6667
if (promptForChoiceData.length === 1) {
6768
return Promise.resolve(data.firstCallOptionName);
@@ -73,7 +74,7 @@ describe("platformEnvironmentRequirements ", () => {
7374
};
7475
}
7576

76-
function mockNativeScriptCloudExtensionService(data: {isInstalled: boolean}) {
77+
function mockNativeScriptCloudExtensionService(data: { isInstalled: boolean }) {
7778
const nativeScriptCloudExtensionService = testInjector.resolve("nativeScriptCloudExtensionService");
7879
nativeScriptCloudExtensionService.isInstalled = () => data.isInstalled;
7980
nativeScriptCloudExtensionService.install = () => { isExtensionInstallCalled = true; };
@@ -124,7 +125,7 @@ describe("platformEnvironmentRequirements ", () => {
124125
mockPrompter({ firstCallOptionName: PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME });
125126
mockNativeScriptCloudExtensionService({ isInstalled: true });
126127

127-
await assert.isRejected(platformEnvironmentRequirements.checkEnvironmentRequirements({ platform, notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true }}));
128+
await assert.isRejected(platformEnvironmentRequirements.checkEnvironmentRequirements({ platform, notConfiguredEnvOptions: { hideSyncToPreviewAppOption: true } }));
128129
assert.isTrue(promptForChoiceData.length === 1);
129130
assert.isTrue(isExtensionInstallCalled);
130131
assert.deepEqual("To continue, choose one of the following options: ", promptForChoiceData[0].message);
@@ -135,13 +136,13 @@ describe("platformEnvironmentRequirements ", () => {
135136
mockPrompter({ firstCallOptionName: PlatformEnvironmentRequirements.CLOUD_SETUP_OPTION_NAME });
136137
mockNativeScriptCloudExtensionService({ isInstalled: true });
137138

138-
await assert.isRejected(platformEnvironmentRequirements.checkEnvironmentRequirements({ platform, notConfiguredEnvOptions: { hideCloudBuildOption: true }}));
139+
await assert.isRejected(platformEnvironmentRequirements.checkEnvironmentRequirements({ platform, notConfiguredEnvOptions: { hideCloudBuildOption: true } }));
139140
assert.isTrue(promptForChoiceData.length === 1);
140141
assert.isTrue(isExtensionInstallCalled);
141142
assert.deepEqual("To continue, choose one of the following options: ", promptForChoiceData[0].message);
142143
assert.deepEqual(['Sync to Playground', 'Configure for Local Builds', 'Skip Step and Configure Manually'], promptForChoiceData[0].choices);
143144
});
144-
it("should skip env check when NS_SKIP_ENV_CHECK environment variable is passed", async() => {
145+
it("should skip env check when NS_SKIP_ENV_CHECK environment variable is passed", async () => {
145146
(<any>process.env).NS_SKIP_ENV_CHECK = true;
146147

147148
const output = await platformEnvironmentRequirements.checkEnvironmentRequirements({ platform });
@@ -153,7 +154,7 @@ describe("platformEnvironmentRequirements ", () => {
153154

154155
describe("when local setup option is selected", () => {
155156
beforeEach(() => {
156-
mockPrompter( {firstCallOptionName: PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME});
157+
mockPrompter({ firstCallOptionName: PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME });
157158
});
158159

159160
it("should return true when env is configured after executing setup script", async () => {
@@ -169,7 +170,7 @@ describe("platformEnvironmentRequirements ", () => {
169170

170171
describe("and env is not configured after executing setup script", () => {
171172
it("should setup manually when cloud extension is installed", async () => {
172-
mockDoctorService( { canExecuteLocalBuild: false, mockSetupScript: true });
173+
mockDoctorService({ canExecuteLocalBuild: false, mockSetupScript: true });
173174
mockPrompter({ firstCallOptionName: PlatformEnvironmentRequirements.LOCAL_SETUP_OPTION_NAME, secondCallOptionName: PlatformEnvironmentRequirements.MANUALLY_SETUP_OPTION_NAME });
174175
mockNativeScriptCloudExtensionService({ isInstalled: true });
175176

0 commit comments

Comments
 (0)