diff --git a/lib/declarations.ts b/lib/declarations.ts index 33fa51a..4d1da80 100644 --- a/lib/declarations.ts +++ b/lib/declarations.ts @@ -33,6 +33,7 @@ interface ISimctl { uninstall(deviceId: string, applicationIdentifier: string, opts?: any): void; notifyPost(deviceId: string, notification: string): void; getDevices(): IDevice[]; + getLog(deviceId: string, predicate?: string): any; getAppContainer(deviceId: string, applicationIdentifier: string): string; } diff --git a/lib/iphone-simulator-common.ts b/lib/iphone-simulator-common.ts index 3069681..f1d7eb2 100644 --- a/lib/iphone-simulator-common.ts +++ b/lib/iphone-simulator-common.ts @@ -36,54 +36,6 @@ export function getInstalledApplications(deviceId: string): IApplication[] { return result; } -export function printDeviceLog(deviceId: string, launchResult?: string): any { - if (launchResult) { - pid = launchResult.split(":")[1].trim(); - } - - if (!isDeviceLogOperationStarted) { - deviceLogChildProcess = this.getDeviceLogProcess(deviceId); - if (deviceLogChildProcess.stdout) { - deviceLogChildProcess.stdout.on("data", (data: NodeBuffer) => { - let dataAsString = data.toString(); - if (pid) { - if (dataAsString.indexOf(`[${pid}]`) > -1) { - process.stdout.write(dataAsString); - } - } else { - process.stdout.write(dataAsString); - } - }); - } - - if (deviceLogChildProcess.stderr) { - deviceLogChildProcess.stderr.on("data", (data: string) => { - let dataAsString = data.toString(); - if (pid) { - if (dataAsString.indexOf(`[${pid}]`) > -1) { - process.stdout.write(dataAsString); - } - } else { - process.stdout.write(dataAsString); - } - process.stdout.write(data.toString()); - }); - } - } - - return deviceLogChildProcess; -} - -export function getDeviceLogProcess(deviceId: string): any { - if (!isDeviceLogOperationStarted) { - let logFilePath = path.join(osenv.home(), "Library", "Logs", "CoreSimulator", deviceId, "system.log"); - deviceLogChildProcess = require("child_process").spawn("tail", ['-f', '-n', '1', logFilePath]); - isDeviceLogOperationStarted = true; - } - - return deviceLogChildProcess; -} - export function startSimulator(deviceId: string): void { let simulatorPath = path.resolve(xcode.getPathFromXcodeSelect(), "Applications", "Simulator.app"); let args = ["open", simulatorPath, '--args', '-CurrentDeviceUDID', deviceId]; diff --git a/lib/iphone-simulator-xcode-simctl.ts b/lib/iphone-simulator-xcode-simctl.ts index ae8b051..b656fd0 100755 --- a/lib/iphone-simulator-xcode-simctl.ts +++ b/lib/iphone-simulator-xcode-simctl.ts @@ -2,6 +2,7 @@ "use strict"; import childProcess = require("./child-process"); +import * as child_process from "child_process"; import errors = require("./errors"); import common = require("./iphone-simulator-common"); @@ -15,8 +16,12 @@ import * as _ from "lodash"; import { IPhoneSimulatorNameGetter } from "./iphone-simulator-name-getter"; +const osenv = require("osenv"); + export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements ISimulator { private static DEVICE_IDENTIFIER_PREFIX = "com.apple.CoreSimulator.SimDeviceType"; + private deviceLogChildProcess: any = null; + private isDeviceLogOperationStarted = false; public defaultDeviceIdentifier = "iPhone 6"; private simctl: ISimctl = null; @@ -115,12 +120,57 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I } } - public printDeviceLog(deviceId: string, launchResult?: string): any { - return common.printDeviceLog(deviceId, launchResult); + public printDeviceLog(deviceId: string, launchResult?: string): child_process.ChildProcess { + let pid = ""; + let deviceLogChildProcess; + + if (launchResult) { + pid = launchResult.split(":")[1].trim(); + } + + if (!this.isDeviceLogOperationStarted) { + deviceLogChildProcess = this.getDeviceLogProcess(deviceId); + if (deviceLogChildProcess.stdout) { + deviceLogChildProcess.stdout.on("data", this.logDataHandler.bind(this, pid)); + } + + if (deviceLogChildProcess.stderr) { + deviceLogChildProcess.stderr.on("data", this.logDataHandler.bind(this, pid)); + } + } + + return deviceLogChildProcess; + } + + private logDataHandler(pid: string, logData: NodeBuffer): void { + const dataAsString = logData.toString(); + + if (pid) { + if (dataAsString.indexOf(`[${pid}]`) > -1) { + process.stdout.write(dataAsString); + } + } else { + process.stdout.write(dataAsString); + } } - public getDeviceLogProcess(deviceId: string): any { - return common.getDeviceLogProcess(deviceId); + public getDeviceLogProcess(deviceId: string, predicate?: string): child_process.ChildProcess { + if (!this.isDeviceLogOperationStarted) { + const device = this.getDeviceFromIdentifier(deviceId); + const deviceVersion = device ? device.runtimeVersion : ""; + const majorVersion = deviceVersion.split(".")[0]; + + if (majorVersion && parseInt(majorVersion) >= 11) { + this.deviceLogChildProcess = this.simctl.getLog(deviceId, predicate); + } else { + const logFilePath = path.join(osenv.home(), "Library", "Logs", "CoreSimulator", deviceId, "system.log"); + this.deviceLogChildProcess = require("child_process").spawn("tail", ['-f', '-n', '1', logFilePath]); + } + + this.isDeviceLogOperationStarted = true; + } + + return this.deviceLogChildProcess; } private getDeviceToRun(): IDevice { @@ -195,6 +245,12 @@ export class XCodeSimctlSimulator extends IPhoneSimulatorNameGetter implements I } } + private getDeviceFromIdentifier(deviceId: string) { + const availableDevices = this.getDevices(); + + return _.find(availableDevices, { id: deviceId }); + } + private killSimulator(): void { childProcess.execSync("pkill -9 -f Simulator"); } diff --git a/lib/simctl.ts b/lib/simctl.ts index 9684d2a..83e6b04 100644 --- a/lib/simctl.ts +++ b/lib/simctl.ts @@ -1,4 +1,5 @@ import childProcess = require("./child-process"); +import * as child_process from "child_process"; import errors = require("./errors"); import options = require("./options"); import * as _ from "lodash"; @@ -120,6 +121,16 @@ export class Simctl implements ISimctl { return devices; } + public getLog(deviceId: string, predicate?: string): child_process.ChildProcess { + let predicateArgs: string[] = []; + + if (predicate) { + predicateArgs = ["--predicate", predicate]; + } + + return this.simctlSpawn("spawn", [deviceId, "log", "stream", "--style", "syslog"].concat(predicateArgs)); + } + private simctlExec(command: string, args: string[], opts?: any): string { const result = childProcess.spawnSync("xcrun", ["simctl", command].concat(args), opts); if (result) { @@ -136,4 +147,8 @@ export class Simctl implements ISimctl { return ''; } + + private simctlSpawn(command: string, args: string[], opts?: child_process.SpawnOptions): child_process.ChildProcess { + return child_process.spawn("xcrun", ["simctl", command].concat(args), opts); + } } diff --git a/package.json b/package.json index 925557c..9b86867 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ios-sim-portable", - "version": "3.1.3", + "version": "3.2.0", "description": "", "main": "./lib/ios-sim.js", "scripts": {