All files ios.js

0% Statements 0/53
0% Branches 0/18
0% Functions 0/20
0% Lines 0/51
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152                                                                                                                                                                                                                                                                                                               
// @flow
 
import _ from 'lodash'
import inquirer from 'inquirer'
import {
  execSync,
  spawn
} from 'child_process'
import spin from './spin'
import ernConfig from './config'
const simctl = require('node-simctl')
 
export type IosDevice = {
  name: string;
  udid: string;
  version: string;
}
 
export async function getiPhoneSimulators () {
  const iosSims = await simctl.getDevices()
  return _.filter(
           _.flattenDeep(
             _.map(iosSims, (val, key) => val)),
        (device) => device.name.match(/^iPhone/))
}
 
export function getiPhoneRealDevices () {
  const devices = execSync('xcrun instruments -s', {encoding: 'utf8'})
  return parseIOSDevicesList(devices)
}
 
export async function askUserToSelectAniPhoneDevice (devices: Array<IosDevice>) {
  const choices = _.map(devices, (val, key) => ({
    name: `${val.name} udid: ${val.udid} version: ${val.version}`,
    value: val
  }))
 
  const { selectedDevice } = await inquirer.prompt([{
    type: 'list',
    name: 'selectedDevice',
    message: 'Choose an iOS device',
    choices: choices
  }])
 
  return selectedDevice
}
 
export async function askUserToSelectAniPhoneSimulator () {
  const iPhoneDevices = await getiPhoneSimulators()
  const choices = _.map(iPhoneDevices, (val, key) => ({
    name: `${val.name} (UDID ${val.udid})`,
    value: val
  }))
 
  // Check if user has set the usePreviousEmulator flag to true
  let emulatorConfig = ernConfig.getValue('emulatorConfig')
  if (choices && emulatorConfig.ios.usePreviousEmulator) {
    // Get the name of previously used simulator
    const simulatorUdid = emulatorConfig.ios.simulatorUdid
    // Check if simulator still exists
    let previousSimulator
    choices.forEach((val) => {
      if (val && val.value.udid === simulatorUdid) {
        previousSimulator = val.value
      }
    })
    if (previousSimulator) {
      return previousSimulator
    }
  }
 
  // if simulator is still not resolved
  let {selectedDevice} = await inquirer.prompt([{
    type: 'list',
    name: 'selectedDevice',
    message: 'Choose an iOS simulator',
    choices
  }])
 
  // Update the emulatorConfig
  emulatorConfig.ios.simulatorUdid = selectedDevice.udid
  ernConfig.setValue('emulatorConfig', emulatorConfig)
 
  return selectedDevice
}
 
export function parseIOSDevicesList (text: string): Array<IosDevice> {
  const devices = []
  text.split('\n').forEach((line) => {
    const device = line.match(/(.*?) \((.*?)\) \[(.*?)\]/)
    const noSimulator = line.match(/(.*?) \((.*?)\) \[(.*?)\] \((.*?)\)/)
    if (device != null && noSimulator == null) {
      var name = device[1]
      var version = device[2]
      var udid = device[3]
      devices.push({udid, name, version})
    }
  })
 
  return devices
}
 
export function killAllRunningSimulators () {
  try {
    execSync(`killall "Simulator" `)
  } catch (e) {
    // do nothing if there is no simulator launched
  }
}
 
export async function launchSimulator (deviceUdid: string) {
  return new Promise((resolve, reject) => {
    const xcrunProc = spawn('xcrun', [ 'instruments', '-w', deviceUdid ])
    xcrunProc.stdout.on('data', data => {
      log.debug(data)
    })
    xcrunProc.stderr.on('data', data => {
      log.debug(data)
    })
    xcrunProc.on('close', code => {
      code === (0 || 255 /* 255 code because we don't provide -t option */)
        ? resolve()
        : reject(new Error(`XCode xcrun command failed with exit code ${code}`))
    })
  })
}
 
export async function runIosApp ({
  appPath,
  bundleId
  } : {
    appPath: string,
    bundleId: string
    }) {
  const iPhoneDevice = await askUserToSelectAniPhoneSimulator()
  killAllRunningSimulators()
  await spin('Waiting for device to boot',
    launchSimulator(iPhoneDevice.udid))
  await spin('Installing application on simulator',
    installApplicationOnSimulator(iPhoneDevice.udid, appPath))
  await spin('Launching application',
    launchApplication(iPhoneDevice.udid, bundleId))
}
 
export async function installApplicationOnSimulator (deviceUdid: string, pathToAppFile: string) {
  return simctl.installApp(deviceUdid, pathToAppFile)
}
 
export async function launchApplication (deviceUdid: string, bundleId: string) {
  return simctl.launch(deviceUdid, bundleId)
}