-
Notifications
You must be signed in to change notification settings - Fork 10
Conversation
child-process.ts
Outdated
try { | ||
return this.spawnFromEvent(command, args, "close", options, spawnFromEventOptions); | ||
} catch (err) { | ||
this.$logger.trace(`Error from trySpawnAwaitCloseEvent method. More info: ${err}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trySpawnAwaitCloseEvent -> trySpawnFromCloseEvent
private $options: ICommonOptions) { } | ||
|
||
public allowedParameters = [this.$stringParameter]; | ||
|
||
public async execute(args: string[]): Promise<void> { | ||
if (this.$options.availableDevices) { | ||
await this.$emulatorImageService.listAvailableEmulators(this.$mobileHelper.validatePlatformName(args[0])); | ||
const platform = this.$mobileHelper.normalizePlatformName(args[0]); | ||
if (!platform && args[0]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we stop using this.$mobileHelper.validatePlatformName
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because when tns devices --available-devices
command was executed, an error was thrown from validatePlatformName
method. I fixed this behaviour.
Actually when the platform is not valid (for example when tns devices invalidplatform
), normalizePlatformName
method will return undefined
and the check above
if (!platform && args[0]) {
will throw an error.
definitions/mobile.d.ts
Outdated
* @param input The options that can be passed to filter the result. | ||
* @returns {Promise<Mobile.IListEmulatorsOutput>} Dictionary with the following format: { ios: { devices: Mobile.IDeviceInfo[], errors: string[] }, android: { devices: Mobile.IDeviceInfo[], errors: string[]}}. | ||
*/ | ||
getAvailableEmulators(input?: Mobile.IListEmulatorsOptions): Promise<Mobile.IListEmulatorsOutput>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
input -> options?
definitions/mobile.d.ts
Outdated
* @param availableDevices - All available devices. | ||
* @returns {Promise<Mobile.IDeviceInfo>} The running emulator if such can be found by provided emulatorId or null otherwise | ||
*/ | ||
getRunningEmulator(emulatorId: string, availableEmulators?: Mobile.IDeviceInfo[]): Promise<Mobile.IDeviceInfo>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the parameters and their XML comments do not match (emulatorId vs emulatorIdOrName and availableEmulators vs availableDevices)
return output | ||
.split(EOL) | ||
.filter(device => !!device) | ||
.filter(device => device !== "List of devices attached"); // TODO: Consider to move this to constants |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to constants or remove the TODO
} | ||
|
||
this.$logger.printInfoMessageOnSameLine("."); | ||
await this.sleep(10000); | ||
await sleep(10000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why exactly 10 secs? Can't we check the boot state more often? (e.g. with an incremental sleep)
case "hw.device.name": result.device = parsedLine[1]; break; | ||
case "abi.type": result.abi = parsedLine[1]; break; | ||
case "skin.name": result.skin = parsedLine[1]; break; | ||
case "sdcard.size": result.sdcard = parsedLine[1]; break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also apply the getAvdManagerDeviceInfo approach here (result[key] = parsedLine[1]
)
commands/device/list-devices.ts
Outdated
@@ -40,6 +48,16 @@ export class ListDevicesCommand implements ICommand { | |||
this.$logger.out(table.toString()); | |||
} | |||
} | |||
|
|||
private outputEmulators(title: string, emulators: Mobile.IDeviceInfo[]) { | |||
this.$logger.out(title); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can support --json
here and just print the stringified information (just an idea, not a merge stopper)
commands/device/list-devices.ts
Outdated
@@ -40,6 +48,16 @@ export class ListDevicesCommand implements ICommand { | |||
this.$logger.out(table.toString()); | |||
} | |||
} | |||
|
|||
private outputEmulators(title: string, emulators: Mobile.IDeviceInfo[]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe rename this to printEmulatorsInfo
constants.ts
Outdated
@@ -39,6 +45,11 @@ export class DeviceDiscoveryEventNames { | |||
static DEVICE_LOST = "deviceLost"; | |||
} | |||
|
|||
export class EmulatorDiscoveryNames { | |||
static AVAILABLE_EMULATOR_FOUND = "availableEmulatorFound"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe emulatorImageFound
and emulatorImageLost
are better names
@@ -587,6 +587,23 @@ export function getValueFromNestedObject(obj: any, key: string): any { | |||
return _.head(_getValueRecursive(obj, key)); | |||
} | |||
|
|||
export function getWinRegPropertyValue(key: string, propertyName: string): Promise<string> { | |||
return new Promise((resolve, reject) => { | |||
const Winreg = require("winreg"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const output = await this.$childProcess.execFile<string>(this.adbFilePath, ['devices']); | ||
return output | ||
.split(EOL) | ||
.filter(device => !!device) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can combine the two filters:
return output
.split(EOL)
.filter(line => !!line && line !== "List of devices attached");
const availableEmulatorsOutput = await this.getAvailableEmulatorsCore(); | ||
const genies = availableEmulatorsOutput.devices; | ||
const runningEmulatorIds = await this.getRunningEmulatorIds(adbDevicesOutput); | ||
const runningEmulators = await Promise.all(runningEmulatorIds.map(emulatorId => this.getRunningEmulatorData(emulatorId, genies))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case one of the action fails, we'll not get data for any of the Genymotion emulators. Consider using settlePromises
try { | ||
return this.$childProcess.spawn(pathToPlayer, ["--vm-name", imageIdentifier], { stdio: "ignore", detached: true }).unref(); | ||
} catch (err) { | ||
this.$logger.trace(`error while starting emulator. More info: ${err}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this catch will never catch anything as we are using async version of the spawn. In case there's error, it will be thrown on nextTick. As we do not have .on("error"
handler for the currently spawned process, the error will be raised as UncaughtException and could lead to many unexpected behaviors.
Also why is the process fired and forget?
return (<string>_.first(output.split(EOL))).trim(); | ||
} | ||
|
||
private get defaultPlayerPath() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type
return "/Applications/Genymotion.app/Contents/MacOS/player.app/Contents/MacOS/player"; | ||
} | ||
|
||
if (this.$hostInfo.isWindows) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe just return "";
*/ | ||
const result: any = await getWinRegPropertyValue("\\Software\\Oracle\\VirtualBox", "InstallDir"); | ||
searchPath = result && result.value ? result.value : null; | ||
} catch (err) { /* */ } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at least trace this error.
I've tried this code and I have issues with Genymotion emulators - I do not have paths to Genymotion executables in my PATH, so my expectation was that the emulators will not be available. However,
I've tried running my app on one of them by passing the name:
After that I've tried with the identifier:
|
Also I'm unable to run my normal emulator via its name (not sure if this is supported):
|
When passing the identifier, emulator starts, but CLI hangs and after some time, it fails with error:
After that, I execute the same command (note - the emulator is already running) and the operation fails with different error:
In fact,
The strange thing is that the name I see for my image is: |
7735819
to
eee133c
Compare
…onged exists but actually it is a valid device that exists. Fix failing QA tests: `tns run android --device fakeId --path TestApp --justlaunch` throws an error
eee133c
to
867bc37
Compare
This PR deletes all legacy, unneeded and duplicated code that is used for working with iOS and Android emulators.
This PR adds the functionalities below:
tns devices android --available-devices
- shows all available Android genymotion and Android avd emulators (previously only avd emulators were shown)tns devices --available-devices
- works correctly and shows all available iOS simulators, Android genymotion and Android avd emulators. (previously does not work)tns run android --device <imageIdentifier>
- it is already possible to run on device with specified imageIdentifier (previously it can run only on emulators specified by identifier or name)This PR exposes emulator api from devicesService. The api consists from the following two methods:
Each available android emulator (NOTE: not running emulator) has the properties below:
Each running android emulator has the properties below:
--timeout
option. This option describes the timeout in miliseconds that {N} CLI will wait emulator boot to complete. It might take too long time on some machines to start native android emulator, so this option is useful in such cases.