@appshuttle.io/bell
Version:
Device and Emulator Library used in Shuttle
159 lines (139 loc) • 6.84 kB
JavaScript
var shell = require('shelljs')
var nodePath = process.execPath ? process.execPath
: (which('node') || which('nodejs'))
shell.config.execPath = nodePath.stdout
IOS_XCODE_SELECT_COMMAND = 'xcode-select'
IOS_XCRUN_COMMAND = 'xcrun'
IOS_DEVICE_STRING_ID_HOLDER = '%DEVICE_STRING_ID%'
IOS_XCRUN_RUN_DEVICE_COMMAND = IOS_XCRUN_COMMAND + ' simctl boot \'' + IOS_DEVICE_STRING_ID_HOLDER + '\''
IOS_XCRUN_APPPATH_HOLDER = '%APP_PATH%'
IOS_XCRUN_INSTALL_APP_COMMAND = 'xcrun simctl install booted ' + IOS_XCRUN_APPPATH_HOLDER
IOS_XCRUN_OPENAPP_BUNDLEID_HOLDER = '%APP_BUNDLE_ID%'
IOS_XCRUN_OPENAPP_COMMAND = 'xcrun simctl launch booted ' + IOS_XCRUN_OPENAPP_BUNDLEID_HOLDER
IOS_INSTRUMENTS_COMMAND = 'instruments'
IOS_INSTRUMENTS_GET_DEVICES_COMMAND = IOS_INSTRUMENTS_COMMAND + ' -s devices'
IOS_SIMCTL_DEVICE_LIST_COMMAND = IOS_XCRUN_COMMAND + ' simctl list --json'
class iOSManager {
constructor (params) {
if (!params) throw new Error('No parameters specified')
if (!params.buildPath) throw new Error('No iOS build path specified')
if (!params.appBundleId) throw new Error('No iOS app bundle id specified')
if (!params.deviceStringID) throw new Error('No iOS device id specified')
this.params = params
this.checkIOSEnvironment = function () {
if (!shell.which(IOS_XCODE_SELECT_COMMAND)) {
shell.echo('No xcode-select command available')
return false
}
if (!shell.which(IOS_XCRUN_COMMAND)) {
shell.echo('No xcrun command available')
return false
}
if (!shell.which(IOS_INSTRUMENTS_COMMAND)) {
shell.echo('No instruments command available')
return false
}
return true
}
this.run = function() {
const context = this
return new Promise((resolve, reject) => {
context.openDevice(context.params.deviceStringID).then(function(resultOpen) {
context.installAppInDevice(context.params.buildPath).then(function(resultInstall) {
context.openAppInDevice(context.params.appBundleId).then(function (openResult) {
resolve({
code: 0,
message: 'App Installed and Running'
})
}).catch(function(error) {
reject(error)
})
}).catch(function(error) {
reject(error)
})
}).catch(function (error) {
reject(error)
})
})
}
this.getAvailableDevices = function() {
return new Promise((resolve, reject) => {
shell.exec(IOS_SIMCTL_DEVICE_LIST_COMMAND, function(code, stdout, stderr) {
if (code === 0) {
resolve(JSON.parse(stdout))
} else {
reject({
code: -1,
message: 'Error executing command to get instruments available devices. Error: ' + stderr
})
}
})
})
}
this.openDevice = function(deviceStringID) {
return new Promise((resolve, reject) => {
shell.exec(IOS_XCRUN_RUN_DEVICE_COMMAND.replace(IOS_DEVICE_STRING_ID_HOLDER, deviceStringID), function(code, stdout, stderr) {
if (code === 0) {
shell.exec('open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/', function(code, stdoutOpenSim, stderrOpenSim) {
if (code === 0) {
resolve(stdoutOpenSim)
} else {
reject({
code: -1,
message: 'Error executing command to open Xcode Simulator App with string ID: ' + deviceStringID + ' with error: ' + stderrOpenSim
})
}
})
} else {
if (stderr.includes('Unable to boot device in current state: Booted')) {
shell.exec('open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/', function(code, stdoutOpenSim, stderrOpenSim) {
if (code === 0) {
resolve(stdoutOpenSim)
} else {
reject({
code: -1,
message: 'Error executing command to open Xcode Simulator App with string ID: ' + deviceStringID + ' with error: ' + stderrOpenSim
})
}
})
} else {
reject({
code: -1,
message: 'Error executing command to open device with string ID: ' + deviceStringID + ' with error: ' + stderr
})
}
}
})
})
}
this.installAppInDevice = function(appPath) {
return new Promise((resolve, reject) => {
shell.exec(IOS_XCRUN_INSTALL_APP_COMMAND.replace(IOS_XCRUN_APPPATH_HOLDER, appPath), function(code, stdout, stderr) {
if (code === 0) {
resolve(stdout)
} else {
reject({
code: -1,
message: 'Error executing command to install app with path: ' + appPath + ' and error: ' + stderr
})
}
})
})
}
this.openAppInDevice = function(appBundleId) {
return new Promise((resolve, reject) => {
shell.exec(IOS_XCRUN_OPENAPP_COMMAND.replace(IOS_XCRUN_OPENAPP_BUNDLEID_HOLDER, appBundleId), function(code, stdout, stderr) {
if (code === 0) {
resolve(stdout)
} else {
reject({
code: -1,
message: 'Error executing command to open app with bundle id: ' + appBundleId + ' and error: ' + stderr
})
}
})
})
}
}
}
module.exports = iOSManager