| 1 | | /*! |
| 2 | | * |
| 3 | | * Copyright (c) 2013 Sebastian Golasch |
| 4 | | * |
| 5 | | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | | * copy of this software and associated documentation files (the "Software"), |
| 7 | | * to deal in the Software without restriction, including without limitation |
| 8 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 9 | | * and/or sell copies of the Software, and to permit persons to whom the |
| 10 | | * Software is furnished to do so, subject to the following conditions: |
| 11 | | * |
| 12 | | * The above copyright notice and this permission notice shall be included |
| 13 | | * in all copies or substantial portions of the Software. |
| 14 | | * |
| 15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 16 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 18 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 20 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 21 | | * DEALINGS IN THE SOFTWARE. |
| 22 | | * |
| 23 | | */ |
| 24 | | |
| 25 | 1 | 'use strict'; |
| 26 | | |
| 27 | | // ext. libs |
| 28 | 1 | var Q = require('q'); |
| 29 | 1 | var os = require('os'); |
| 30 | 1 | var cp = require('child_process'); |
| 31 | 1 | var appium = require('appium/lib/server/main'); |
| 32 | 1 | var portscanner = require('portscanner'); |
| 33 | | |
| 34 | | /** |
| 35 | | * This module is a browser plugin for [DalekJS](//github.com/dalekjs/dalek). |
| 36 | | * It provides all a WebDriverServer & browser launcher for Safari on iOS. |
| 37 | | * |
| 38 | | * At the moment this only works with the IPhone |
| 39 | | * |
| 40 | | * The browser plugin can be installed with the following command: |
| 41 | | * |
| 42 | | * ```bash |
| 43 | | * $ npm install dalek-browser-ios --save-dev |
| 44 | | * ``` |
| 45 | | * |
| 46 | | * You can use the browser plugin by adding a config option to the your Dalekfile |
| 47 | | * |
| 48 | | * ```javascript |
| 49 | | * "browsers": ["ios"] |
| 50 | | * ``` |
| 51 | | * |
| 52 | | * Or you can tell Dalek that it should test in this browser via the command line: |
| 53 | | * |
| 54 | | * ```bash |
| 55 | | * $ dalek mytest.js -b ios |
| 56 | | * ``` |
| 57 | | * |
| 58 | | * The Webdriver Server tries to open Port 9003 by default, |
| 59 | | * if this port is blocked, it tries to use a port between 9004 & 9093 |
| 60 | | * You can specifiy a different port from within your [Dalekfile](/pages/config.html) like so: |
| 61 | | * |
| 62 | | * ```javascript |
| 63 | | * "browsers": { |
| 64 | | * "ios": { |
| 65 | | * "port": 5555 |
| 66 | | * } |
| 67 | | * } |
| 68 | | * ``` |
| 69 | | * |
| 70 | | * It is also possible to specify a range of ports: |
| 71 | | * |
| 72 | | * ```javascript |
| 73 | | * "browsers": { |
| 74 | | * "ios": { |
| 75 | | * "portRange": [6100, 6120] |
| 76 | | * } |
| 77 | | * } |
| 78 | | * ``` |
| 79 | | * |
| 80 | | * If you would like to test on the IPad (IPhone) emulator, you can simply apply a snd. argument, |
| 81 | | * which defines the browser type: |
| 82 | | * |
| 83 | | * ```bash |
| 84 | | * $ dalek mytest.js -b ios:ipad |
| 85 | | * ``` |
| 86 | | * |
| 87 | | * @module DalekJS |
| 88 | | * @class IosDriver |
| 89 | | * @namespace Browser |
| 90 | | * @part iOS |
| 91 | | * @api |
| 92 | | */ |
| 93 | | |
| 94 | 1 | var IosDriver = { |
| 95 | | |
| 96 | | /** |
| 97 | | * Verbose version of the browser name |
| 98 | | * |
| 99 | | * @property longName |
| 100 | | * @type string |
| 101 | | * @default Mobile Safari iOS |
| 102 | | */ |
| 103 | | |
| 104 | | longName: 'Mobile Safari iOS (iPhone)', |
| 105 | | |
| 106 | | /** |
| 107 | | * Default port of the Appium WebDriverServer |
| 108 | | * The port may change, cause the port conflict resolution |
| 109 | | * tool might pick another one, if the default one is blocked |
| 110 | | * |
| 111 | | * @property port |
| 112 | | * @type integer |
| 113 | | * @default 4723 |
| 114 | | */ |
| 115 | | |
| 116 | | port: 4723, |
| 117 | | |
| 118 | | /** |
| 119 | | * WebHook port |
| 120 | | * |
| 121 | | * @property webhookPort |
| 122 | | * @type integer |
| 123 | | * @default 9003 |
| 124 | | */ |
| 125 | | |
| 126 | | webhookPort: 9003, |
| 127 | | |
| 128 | | /** |
| 129 | | * Default host of the Appium WebDriverServer |
| 130 | | * The host may be overridden with |
| 131 | | * a user configured value |
| 132 | | * |
| 133 | | * @property host |
| 134 | | * @type string |
| 135 | | * @default localhost |
| 136 | | */ |
| 137 | | |
| 138 | | host: 'localhost', |
| 139 | | |
| 140 | | /** |
| 141 | | * Root path of the appium webdriver server |
| 142 | | * |
| 143 | | * @property path |
| 144 | | * @type string |
| 145 | | * @default /wd/hub |
| 146 | | */ |
| 147 | | |
| 148 | | path: '/wd/hub', |
| 149 | | |
| 150 | | /** |
| 151 | | * Default desired capabilities that should be |
| 152 | | * transferred when the browser session gets requested |
| 153 | | * |
| 154 | | * @property desiredCapabilities |
| 155 | | * @type object |
| 156 | | */ |
| 157 | | |
| 158 | | desiredCapabilities: { |
| 159 | | device: 'iPhone Emulator', |
| 160 | | name: 'Safari remote via WD', |
| 161 | | app: 'safari', |
| 162 | | version: '6.1', |
| 163 | | browserName: '' |
| 164 | | }, |
| 165 | | |
| 166 | | /** |
| 167 | | * Driver defaults, what should the driver be able to access. |
| 168 | | * |
| 169 | | * @property driverDefaults |
| 170 | | * @type object |
| 171 | | */ |
| 172 | | |
| 173 | | driverDefaults: { |
| 174 | | viewport: true, |
| 175 | | status: { |
| 176 | | os: { |
| 177 | | arch: os.arch(), |
| 178 | | version: os.release(), |
| 179 | | name: 'Mac OSX' |
| 180 | | } |
| 181 | | }, |
| 182 | | sessionInfo: true |
| 183 | | }, |
| 184 | | |
| 185 | | /** |
| 186 | | * Special arguments that are needed to invoke |
| 187 | | * appium. These are the defaults, they need to be modified later on |
| 188 | | * |
| 189 | | * @property appiumArgs |
| 190 | | * @type object |
| 191 | | */ |
| 192 | | |
| 193 | | appiumArgs: { |
| 194 | | app: null, |
| 195 | | ipa: null, |
| 196 | | quiet: true, |
| 197 | | udid: null, |
| 198 | | keepArtifacts: false, |
| 199 | | noSessionOverride: false, |
| 200 | | fullReset: false, |
| 201 | | noReset: false, |
| 202 | | launch: false, |
| 203 | | log: false, |
| 204 | | nativeInstrumentsLib: false, |
| 205 | | safari: false, |
| 206 | | forceIphone: false, |
| 207 | | forceIpad: false, |
| 208 | | orientation: null, |
| 209 | | useKeystore: false, |
| 210 | | address: '0.0.0.0', |
| 211 | | nodeconfig: null, |
| 212 | | port: null, |
| 213 | | webhook: null |
| 214 | | }, |
| 215 | | |
| 216 | | /** |
| 217 | | * Different browser types (iPhone / iPad) |
| 218 | | * |
| 219 | | * @property browserTypes |
| 220 | | * @type object |
| 221 | | */ |
| 222 | | |
| 223 | | browserTypes: { |
| 224 | | |
| 225 | | /** |
| 226 | | * IPad emulator |
| 227 | | * |
| 228 | | * @property ipad |
| 229 | | * @type object |
| 230 | | */ |
| 231 | | |
| 232 | | ipad: { |
| 233 | | name: 'iPad' |
| 234 | | } |
| 235 | | |
| 236 | | }, |
| 237 | | |
| 238 | | /** |
| 239 | | * Resolves the driver port |
| 240 | | * |
| 241 | | * @method getPort |
| 242 | | * @return {integer} port WebDriver server port |
| 243 | | */ |
| 244 | | |
| 245 | | getPort: function () { |
| 246 | 0 | return this.port; |
| 247 | | }, |
| 248 | | |
| 249 | | /** |
| 250 | | * Resolves the maximum range for the driver port |
| 251 | | * |
| 252 | | * @method getMaxPort |
| 253 | | * @return {integer} port Max WebDriver server port range |
| 254 | | */ |
| 255 | | |
| 256 | | getMaxPort: function () { |
| 257 | 0 | return this.maxPort; |
| 258 | | }, |
| 259 | | |
| 260 | | /** |
| 261 | | * Resolves the webhook port |
| 262 | | * |
| 263 | | * @method getWebhookPort |
| 264 | | * @return {integer} WebHook server port |
| 265 | | */ |
| 266 | | |
| 267 | | getWebhookPort: function () { |
| 268 | 0 | return this.webhookPort; |
| 269 | | }, |
| 270 | | |
| 271 | | /** |
| 272 | | * Resolves the maximum range for the webhook port |
| 273 | | * |
| 274 | | * @method getWebhookPort |
| 275 | | * @return {integer} WebHook Max WebHook port |
| 276 | | */ |
| 277 | | |
| 278 | | getMaxWebhookPort: function () { |
| 279 | 0 | return this.maxWebhookPort; |
| 280 | | }, |
| 281 | | |
| 282 | | /** |
| 283 | | * Returns the driver host |
| 284 | | * |
| 285 | | * @method getHost |
| 286 | | * @return {string} host WebDriver server hostname |
| 287 | | */ |
| 288 | | |
| 289 | | getHost: function () { |
| 290 | 0 | return this.host; |
| 291 | | }, |
| 292 | | |
| 293 | | /** |
| 294 | | * Launches appium & corresponding emulator or device, |
| 295 | | * kicks off the portscanner |
| 296 | | * |
| 297 | | * @method launch |
| 298 | | * @param {object} configuration Browser configuration |
| 299 | | * @param {EventEmitter2} events EventEmitter (Reporter Emitter instance) |
| 300 | | * @param {Dalek.Internal.Config} config Dalek configuration class |
| 301 | | * @return {object} promise Browser promise |
| 302 | | */ |
| 303 | | |
| 304 | | launch: function (configuration, events, config) { |
| 305 | 0 | var deferred = Q.defer(); |
| 306 | | |
| 307 | | // store injected configuration/log event handlers |
| 308 | 0 | this.reporterEvents = events; |
| 309 | 0 | this.configuration = configuration; |
| 310 | 0 | this.config = config; |
| 311 | | |
| 312 | | // check if the user wants to run the iPad emulator |
| 313 | 0 | if (configuration && configuration.type === 'ipad') { |
| 314 | 0 | this.longName = this.longName.replace('iPhone', 'iPad'); |
| 315 | 0 | this.appiumArgs.forceIpad = true; |
| 316 | | } |
| 317 | | |
| 318 | | // check for a user set port |
| 319 | 0 | var browsers = this.config.get('browsers'); |
| 320 | 0 | if (browsers && Array.isArray(browsers)) { |
| 321 | 0 | browsers.forEach(this._checkUserDefinedPorts.bind(this)); |
| 322 | | } |
| 323 | | |
| 324 | | // check if the current port is in use, if so, scan for free ports |
| 325 | 0 | portscanner.findAPortNotInUse(this.getPort(), this.getMaxPort(), this.getHost(), this._checkPorts.bind(this, deferred)); |
| 326 | 0 | return deferred.promise; |
| 327 | | }, |
| 328 | | |
| 329 | | /** |
| 330 | | * Kills the Appium Server process, |
| 331 | | * kills simulator processses |
| 332 | | * with a slight timeout to prevent |
| 333 | | * appium from throwing errors |
| 334 | | * |
| 335 | | * @method kill |
| 336 | | * @chainable |
| 337 | | */ |
| 338 | | |
| 339 | | kill: function () { |
| 340 | | // kill appium servers |
| 341 | 0 | this.appiumServer.webSocket.server.close(); |
| 342 | 0 | this.appiumServer.rest.listen().close(); |
| 343 | | // slight timeout for process killing |
| 344 | 0 | setTimeout(this._processes.bind(this, this._kill.bind(this)), 1000); |
| 345 | 0 | return this; |
| 346 | | }, |
| 347 | | |
| 348 | | /** |
| 349 | | * Kills the non blacklisted simulator processes & restores |
| 350 | | * the stderr handler |
| 351 | | * |
| 352 | | * @method _kill |
| 353 | | * @param {object|null} err Error or null |
| 354 | | * @param {array} result List of currently running simulator processes |
| 355 | | * @chainable |
| 356 | | * @private |
| 357 | | */ |
| 358 | | |
| 359 | | _kill: function (err, result) { |
| 360 | | // kill simulator processes |
| 361 | 0 | result.forEach(this._killProcess.bind(this)); |
| 362 | | // (re)establish stderr/stdout stream |
| 363 | 0 | this._reinstantiateLog(); |
| 364 | 0 | return this; |
| 365 | | }, |
| 366 | | |
| 367 | | /** |
| 368 | | * Checks a blacklist & kills the process when |
| 369 | | * not found |
| 370 | | * |
| 371 | | * @method _killProcess |
| 372 | | * @param {integer} processID Process ID |
| 373 | | * @chainable |
| 374 | | * @private |
| 375 | | */ |
| 376 | | |
| 377 | | _killProcess: function (processID) { |
| 378 | 0 | var kill = true; |
| 379 | | |
| 380 | | // walk through the list of processes that are |
| 381 | | // open before the driver started |
| 382 | 0 | this.openProcesses.forEach(function (pid) { |
| 383 | 0 | if (pid === processID) { |
| 384 | 0 | kill = false; |
| 385 | | } |
| 386 | | }); |
| 387 | | |
| 388 | 0 | if (kill === true) { |
| 389 | 0 | cp.spawn('kill', [processID]); |
| 390 | | } |
| 391 | | |
| 392 | 0 | return this; |
| 393 | | }, |
| 394 | | |
| 395 | | /** |
| 396 | | * Checks & switches the appium server port, |
| 397 | | * scans the range for the webhook port |
| 398 | | * |
| 399 | | * @method _listProcesses |
| 400 | | * @param {object} deferred Promise |
| 401 | | * @param {object|null} err Error or null |
| 402 | | * @param {integer} port Appium server port to use |
| 403 | | * @chainable |
| 404 | | * @private |
| 405 | | */ |
| 406 | | |
| 407 | | _checkPorts: function (deferred, error, port) { |
| 408 | | // check if the port was blocked & if we need to switch to another port |
| 409 | 0 | if (this.port !== port) { |
| 410 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to port: ' + port); |
| 411 | 0 | this.port = port; |
| 412 | | } |
| 413 | | |
| 414 | | // check if the current webhook port is in use, if so, scan for free ports |
| 415 | 0 | portscanner.findAPortNotInUse(this.getWebhookPort(), this.getMaxWebhookPort(), this.getHost(), this._launch.bind(this, deferred)); |
| 416 | 0 | return this; |
| 417 | | }, |
| 418 | | |
| 419 | | /** |
| 420 | | * Checks & switches the webhook port, |
| 421 | | * loads a list of running simulator processes |
| 422 | | * |
| 423 | | * @method _listProcesses |
| 424 | | * @param {object} deferred Promise |
| 425 | | * @param {object|null} err Error or null |
| 426 | | * @param {integer} port Webhook port to use |
| 427 | | * @chainable |
| 428 | | * @private |
| 429 | | */ |
| 430 | | |
| 431 | | _launch: function (deferred, error, port) { |
| 432 | | // check if the port was blocked & if we need to switch to another port |
| 433 | 0 | if (this.webhookPort !== port) { |
| 434 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to webhook port: ' + port); |
| 435 | 0 | this.webhookPort = port; |
| 436 | | } |
| 437 | | |
| 438 | | // launch appium & the emulator |
| 439 | 0 | this._processes(this._listProcesses.bind(this, deferred)); |
| 440 | 0 | return this; |
| 441 | | }, |
| 442 | | |
| 443 | | /** |
| 444 | | * Stores open processes, |
| 445 | | * suppresses stdout logs, |
| 446 | | * starts appium |
| 447 | | * |
| 448 | | * @method _listProcesses |
| 449 | | * @param {object} deferred Promise |
| 450 | | * @param {object|null} err Error or null |
| 451 | | * @param {array} result List of currently running simulator processes |
| 452 | | * @chainable |
| 453 | | * @private |
| 454 | | */ |
| 455 | | |
| 456 | | _listProcesses: function (deferred, err, result) { |
| 457 | | // save list of open emulator processes, before we launched it |
| 458 | 0 | this.openProcesses = result; |
| 459 | | // nasty hack to surpress socket.io debug reports from appium |
| 460 | 0 | this._suppressAppiumLogs(); |
| 461 | | // run appium |
| 462 | 0 | appium.run(this._loadAppiumArgs(this.appiumArgs), this._afterAppiumStarted.bind(this, deferred)); |
| 463 | 0 | return this; |
| 464 | | }, |
| 465 | | |
| 466 | | /** |
| 467 | | * Stores the appium server reference, |
| 468 | | * restores the stdout logs |
| 469 | | * |
| 470 | | * @method _afterAppiumStarted |
| 471 | | * @param {object} deferred Promise |
| 472 | | * @param {object} appiumServer Appium server instance |
| 473 | | * @chainable |
| 474 | | * @private |
| 475 | | */ |
| 476 | | |
| 477 | | _afterAppiumStarted: function (deferred, appiumServer) { |
| 478 | 0 | this.appiumServer = appiumServer; |
| 479 | 0 | deferred.resolve(); |
| 480 | 0 | return this; |
| 481 | | }, |
| 482 | | |
| 483 | | /** |
| 484 | | * Configures appium |
| 485 | | * |
| 486 | | * @method _loadAppiumArgs |
| 487 | | * @param {object} appiumArgs Appium specific configuration |
| 488 | | * @return {object} Modified appium configuration |
| 489 | | * @private |
| 490 | | */ |
| 491 | | |
| 492 | | _loadAppiumArgs: function (appiumArgs) { |
| 493 | 0 | appiumArgs.port = this.getPort(); |
| 494 | 0 | appiumArgs.webhook = this.getHost() + ':' + this.getWebhookPort(); |
| 495 | 0 | return appiumArgs; |
| 496 | | }, |
| 497 | | |
| 498 | | /** |
| 499 | | * Process user defined ports |
| 500 | | * |
| 501 | | * @method _checkUserDefinedPorts |
| 502 | | * @param {object} browser Browser configuration |
| 503 | | * @chainable |
| 504 | | * @private |
| 505 | | */ |
| 506 | | |
| 507 | | _checkUserDefinedPorts: function (browser) { |
| 508 | 0 | this._checkAppiumPorts(browser); |
| 509 | 0 | this._checkWebhookPorts(browser); |
| 510 | 0 | return this; |
| 511 | | }, |
| 512 | | |
| 513 | | /** |
| 514 | | * Process user defined appium ports |
| 515 | | * |
| 516 | | * @method _checkAppiumPorts |
| 517 | | * @param {object} browser Browser configuration |
| 518 | | * @chainable |
| 519 | | * @private |
| 520 | | */ |
| 521 | | |
| 522 | | _checkAppiumPorts: function (browser) { |
| 523 | | // check for a single defined port |
| 524 | 0 | if (browser.ios && browser.ios.port) { |
| 525 | 0 | this.port = parseInt(browser.ios.port, 10); |
| 526 | 0 | this.maxPort = this.port + 90; |
| 527 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to user defined port: ' + this.port); |
| 528 | | } |
| 529 | | |
| 530 | | // check for a port range |
| 531 | 0 | if (browser.ios && browser.ios.portRange && browser.ios.portRange.length === 2) { |
| 532 | 0 | this.port = parseInt(browser.ios.portRange[0], 10); |
| 533 | 0 | this.maxPort = parseInt(browser.ios.portRange[1], 10); |
| 534 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to user defined port(s): ' + this.port + ' -> ' + this.maxPort); |
| 535 | | } |
| 536 | | |
| 537 | 0 | return this; |
| 538 | | }, |
| 539 | | |
| 540 | | /** |
| 541 | | * Process user defined webhook ports |
| 542 | | * |
| 543 | | * @method _checkWebhookPorts |
| 544 | | * @param {object} browser Browser configuration |
| 545 | | * @chainable |
| 546 | | * @private |
| 547 | | */ |
| 548 | | |
| 549 | | _checkWebhookPorts: function (browser) { |
| 550 | | // check for a single defined webhook port |
| 551 | 0 | if (browser.ios && browser.ios.webhookPort) { |
| 552 | 0 | this.webhookPort = parseInt(browser.ios.webhookPort, 10); |
| 553 | 0 | this.maxWebhookPort = this.webhookPort + 90; |
| 554 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to user defined webhook port: ' + this.webhookPort); |
| 555 | | } |
| 556 | | |
| 557 | | // check for a webhook port range |
| 558 | 0 | if (browser.ios && browser.ios.webhookPortRange && browser.ios.webhookPortRange.length === 2) { |
| 559 | 0 | this.webhookPort = parseInt(browser.ios.webhookPortRange[0], 10); |
| 560 | 0 | this.maxWebhookPort = parseInt(browser.ios.webhookPortRange[1], 10); |
| 561 | 0 | this.reporterEvents.emit('report:log:system', 'dalek-browser-ios: Switching to user defined webhook port(s): ' + this.webhookPort + ' -> ' + this.maxWebhookPort); |
| 562 | | } |
| 563 | | |
| 564 | 0 | return this; |
| 565 | | }, |
| 566 | | |
| 567 | | /** |
| 568 | | * Tracks running simulator processes |
| 569 | | * |
| 570 | | * @method _processes |
| 571 | | * @param {function} fn Callback |
| 572 | | * @chainable |
| 573 | | * @private |
| 574 | | */ |
| 575 | | |
| 576 | | _processes: function (fn) { |
| 577 | 0 | var cmd = ['ps -ax', '|', 'grep "iPhone Simulator.app"']; |
| 578 | 0 | cp.exec(cmd.join(' '), this._transformProcesses.bind(this, fn)); |
| 579 | 0 | return this; |
| 580 | | }, |
| 581 | | |
| 582 | | /** |
| 583 | | * Transforms the process list output into |
| 584 | | * a json structure |
| 585 | | * |
| 586 | | * @method _transformProcesses |
| 587 | | * @param {function} fn Callback |
| 588 | | * @param {null|object} err Error if error, null if not |
| 589 | | * @param {string} stdout Terminal output |
| 590 | | * @chainable |
| 591 | | * @private |
| 592 | | */ |
| 593 | | |
| 594 | | _transformProcesses: function(fn, err, stdout){ |
| 595 | 0 | var result = []; |
| 596 | 0 | stdout.split('\n').forEach(this._scanProcess.bind(this, result)); |
| 597 | 0 | fn(err, result); |
| 598 | 0 | return this; |
| 599 | | }, |
| 600 | | |
| 601 | | /** |
| 602 | | * Scans and transforms the process list |
| 603 | | * |
| 604 | | * @method _scanProcess |
| 605 | | * @param {array} result Transformed result |
| 606 | | * @param {string} line Process list entry |
| 607 | | * @chainable |
| 608 | | * @private |
| 609 | | */ |
| 610 | | |
| 611 | | _scanProcess: function (result, line){ |
| 612 | 0 | var data = line.split(' '); |
| 613 | 0 | data = data.filter(this._filterProcessItem); |
| 614 | | |
| 615 | 0 | if (data[1] === '??') { |
| 616 | 0 | result.push(data[0]); |
| 617 | | } |
| 618 | | |
| 619 | 0 | return this; |
| 620 | | }, |
| 621 | | |
| 622 | | /** |
| 623 | | * Filters process list items |
| 624 | | * |
| 625 | | * @method _filterProcessItem |
| 626 | | * @param {string} item Process list entry |
| 627 | | * @return {bool|string} Process item or false |
| 628 | | * @private |
| 629 | | */ |
| 630 | | |
| 631 | | _filterProcessItem: function (item) { |
| 632 | 0 | if (item !== '') { |
| 633 | 0 | return item; |
| 634 | | } |
| 635 | | |
| 636 | 0 | return false; |
| 637 | | }, |
| 638 | | |
| 639 | | /** |
| 640 | | * Overwrite default stdout & stderr handler |
| 641 | | * to suppress some appium logs |
| 642 | | * |
| 643 | | * @method _suppressAppiumLogs |
| 644 | | * @chainable |
| 645 | | * @private |
| 646 | | */ |
| 647 | | |
| 648 | | _suppressAppiumLogs: function () { |
| 649 | | // TODO: Check if the log level of appium can be set to 0 |
| 650 | 0 | var _supLogs = function (data) { |
| 651 | 0 | if (data.search('6minfo') === -1 && data.search('33mwarn') === -1 && data.search('90mdebug') === -1) { |
| 652 | 0 | this.oldWrite.bind(process.stdout)(data); |
| 653 | | } |
| 654 | | }.bind(this); |
| 655 | | |
| 656 | | // store old std. handler |
| 657 | 0 | this.oldWrite = process.stdout.write; |
| 658 | 0 | this.oldWriteErr = process.stderr.write; |
| 659 | | |
| 660 | | // overwrite with ugliness |
| 661 | 0 | process.stdout.write = _supLogs; |
| 662 | 0 | process.stderr.write = _supLogs; |
| 663 | 0 | return this; |
| 664 | | }, |
| 665 | | |
| 666 | | /** |
| 667 | | * Reinstantiate stdout handler after appium has |
| 668 | | * been started |
| 669 | | * |
| 670 | | * @method _reinstantiateLog |
| 671 | | * @chainable |
| 672 | | * @private |
| 673 | | */ |
| 674 | | |
| 675 | | _reinstantiateLog: function () { |
| 676 | 0 | setTimeout(function () { |
| 677 | 0 | process.stdout.write = this.oldWrite; |
| 678 | 0 | process.stderr.write = this.oldWriteErr; |
| 679 | | }.bind(this), 8000); |
| 680 | 0 | return this; |
| 681 | | } |
| 682 | | |
| 683 | | }; |
| 684 | | |
| 685 | | // expose the module |
| 686 | 1 | module.exports = IosDriver; |
| 687 | | |