Skip to content

Add debug method to the public API #2677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 7, 2017

Conversation

TsvetanMilanov
Copy link
Contributor

@TsvetanMilanov TsvetanMilanov commented Mar 30, 2017

We need to add debug service to the public API of the {N} CLI. This service should have method which starts debugging and returns the chrome devtools url. With this service it will be possible to use the CLI as a library and start debugging.
This PR includes:

  • Return the results from the action in devicesService.execute(action)
  • Remove the this.$options from both android and ios debug services
  • Remove the projectData dependency from both android and ios debug services
  • Add the new debug service which will be used in the public API

Common lib reference: telerik/mobile-cli-lib#927

@TsvetanMilanov TsvetanMilanov self-assigned this Mar 30, 2017
@TsvetanMilanov TsvetanMilanov force-pushed the milanov/add-debug-method-to-the-public-api branch 3 times, most recently from e9548d6 to 6ca7280 Compare March 31, 2017 11:29
protected $platformService: IPlatformService,
protected $projectData: IProjectData,
protected $options: IOptions,
protected $platformsData: IPlatformsData) {
this.$projectData.initializeProjectData();
}
this.$projectData.initializeProjectData(this.$options.path);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can skip passing this.$options.path here - it'll default to it anyways

}

private getPathToAppPackage(debugService: IPlatformDebugService, options: IOptions, buildConfig: IBuildConfig): string {
if (debugService.platform === this.$devicePlatformsConstants.Android) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to use $mobileHelper.isAndroidPlatform here in case the casing differs

} else {
return null;
}
} else if (debugService.platform === this.$devicePlatformsConstants.iOS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here $mobileHelper.isiOSPlatform

import { EventEmitter } from "events";

export abstract class DebugServiceBase extends EventEmitter implements IPlatformDebugService {
constructor() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't such a constructor gratuitous?

// TODO: Check if app is running.
const isAppRunning = true;
let result: string[];
if (device.deviceInfo.platform === this.$devicePlatformsConstants.iOS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark about $mobileHelper.isiOSPlatform

}

result = await debugService.debug(debugData, debugOptions);
} else if (device.deviceInfo.platform === this.$devicePlatformsConstants.Android) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$mobileHelper

this.$devicesService.execute(async (device: Mobile.IiOSDevice) => await device.isEmulator ? this.emulatorDebugBrk(projectData, buildConfig) : this.debugBrkCore(device, projectData));
public async debugStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise<void> {
await this.$devicesService.initialize({ platform: this.platform, deviceId: debugData.deviceIdentifier });
const action = async (device: Mobile.IiOSDevice) => await device.isEmulator ? this.emulatorDebugBrk(debugData, false, debugOptions) : this.debugBrkCore(device, debugData, debugOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The await operator here seems misplaced

if (this.$options.debugBrk) {
await this.getDebugService(platform).debug(projectData, buildConfig);
const debugService = this.getDebugService(platform); const deployOptions: IDeployPlatformOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deployOptions can be declared above the if statement in order to avoid repetition

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why they've been declared there so far 😃

test/debug.ts Outdated
@@ -43,6 +43,9 @@ function createTestInjector(): IInjector {
testInjector.register("projectTemplatesService", {});
testInjector.register("xmlValidator", {});
testInjector.register("npm", {});
testInjector.register("debugDataService", {
createDebugData: () => { return {}; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the short-hand syntax here:
createDebugData: () => ({})

}

port = candidatePort;
port = await getAvailablePort(40000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we start from 40000?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we want to start chrome devtools on port 40000 each time we start debugging. That's why we don't get random free port. If we get random free port, the users should copy the url each time tns debug is executed.

const platformData = this.getPlatformData(debugService);

return this.$platformService.getLatestApplicationPackageForDevice(platformData, buildConfig).packageName;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need the else? Can't you place the return null at the end of the method?

}
}

protected getPlatformData(debugService: IPlatformDebugService): IPlatformData {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this method protected and not private?

import { EventEmitter } from "events";
import { CONNECTION_ERROR_EVENT_NAME } from "../constants";

class DebugService extends EventEmitter {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't you implement IDebugService as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This debug service has different debug method. In ios/android debug service the debug method returns array of the chrome devtools urls. In this service we want to start debugging only on one device and return the url only for it.

const device = this.$devicesService.getDeviceByIdentifier(debugData.deviceIdentifier);
const debugService = this.getDebugService(device);

debugService.on(CONNECTION_ERROR_EVENT_NAME, (e: Error) => this.emit(CONNECTION_ERROR_EVENT_NAME, e));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who will remove this handler? In case you call debug method three times, you'll have three handlers for the error event. So in case an error is raised, the one who listens for DebugService's CONNECTION_ERROR_EVENT_NAME event will receive three errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also why the handler is attached before the if (!device) statement. It looks like the handler has meaning only when we have a device.


result = await debugService.debug(debugData, debugOptions);
} else if (device.deviceInfo.platform === this.$devicePlatformsConstants.Android) {
debugOptions.client = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be valid for iOS instead of Android?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debugOptions.client in the android debug service is the same as debugOptions.chrome in ios debug service. I changed the android debug service to use debugOptions.chrome.

private async deviceDebugBrk(projectData: IProjectData, buildConfig: IBuildConfig, shouldBreak?: boolean): Promise<void> {
await this.$devicesService.initialize({ platform: this.platform, deviceId: this.$options.device });
this.$devicesService.execute(async (device: iOSDevice.IOSDevice) => {
private async deviceDebugBrk(debugData: IDebugData, shouldBreak: boolean, debugOptions: IDebugOptions): Promise<string[]> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't shouldBreak a debug option? Can't we place it in debugOptions object?
P.S. I do not like passing boolean arguments.

return result;
};

const result = await this.$devicesService.execute(action, this.getCanExecuteAction(debugData.deviceIdentifier));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

results sounds better

private async deviceStart(debugData: IDebugData, debugOptions: IDebugOptions): Promise<string[]> {
await this.$devicesService.initialize({ platform: this.platform, deviceId: debugData.deviceIdentifier });
const action = async (device: Mobile.IiOSDevice) => device.isEmulator ? await this.emulatorStart(debugData, debugOptions) : await this.deviceStartCore(device, debugData, debugOptions);
const result = await this.$devicesService.execute(action, this.getCanExecuteAction(debugData.deviceIdentifier));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

results

if (this.$options.debugBrk) {
await this.getDebugService(platform).debug(projectData, buildConfig);
const debugService = this.getDebugService(platform); const deployOptions: IDeployPlatformOptions = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why they've been declared there so far 😃

@TsvetanMilanov TsvetanMilanov force-pushed the milanov/add-debug-method-to-the-public-api branch from 61bf525 to 6bd76ad Compare April 5, 2017 15:19
Copy link
Contributor

@Mitko-Kerezov Mitko-Kerezov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@TsvetanMilanov TsvetanMilanov force-pushed the milanov/add-debug-method-to-the-public-api branch from 6bd76ad to 1cd6874 Compare April 7, 2017 10:26
@TsvetanMilanov TsvetanMilanov force-pushed the milanov/add-debug-method-to-the-public-api branch from 1cd6874 to 3d9c6b1 Compare April 7, 2017 10:30
@TsvetanMilanov TsvetanMilanov force-pushed the milanov/add-debug-method-to-the-public-api branch from 3d9c6b1 to 8f79755 Compare April 7, 2017 10:37
@TsvetanMilanov TsvetanMilanov merged commit 1b19adf into master Apr 7, 2017
@TsvetanMilanov TsvetanMilanov deleted the milanov/add-debug-method-to-the-public-api branch April 7, 2017 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants