diff --git a/.gitmodules b/.gitmodules index 47332214b..bea75b2b5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,9 +16,6 @@ [submodule "submodules/unlock_apk"] path = submodules/unlock_apk url = https://github.com/appium/unlock_apk.git -[submodule "submodules/SafariLauncher"] - path = submodules/SafariLauncher - url = https://github.com/snevesbarros/SafariLauncher.git [submodule "submodules/libimobiledevice-macosx"] path = submodules/libimobiledevice-macosx url = https://github.com/benvium/libimobiledevice-macosx.git diff --git a/grunt-helpers.js b/grunt-helpers.js index 6c565457d..33d44fdf7 100644 --- a/grunt-helpers.js +++ b/grunt-helpers.js @@ -355,7 +355,7 @@ module.exports.signApp = function (appName, certName, cb) { }; module.exports.buildSafariLauncherApp = function (cb, sdk, xcconfig) { - var appRoot = path.resolve(__dirname, "submodules", "SafariLauncher"); + var appRoot = path.resolve(require.resolve('safari-launcher'), '..'); module.exports.build(appRoot, function (err) { if (err !== null) { console.log(err); diff --git a/lib/devices/ios/ios.js b/lib/devices/ios/ios.js index 43ee3f3f8..6c62491dc 100644 --- a/lib/devices/ios/ios.js +++ b/lib/devices/ios/ios.js @@ -328,48 +328,30 @@ IOS.prototype.startInstruments = function (cb) { }); }.bind(this); - if (this.shouldIgnoreInstrumentsExit()) { - // for safari on a real device, instruments is going to crash, but we - // expect that and ignore it - logger.debug("Not starting command proxy since we're expecting that " + - "Instruments won't be able to talk to it anyway"); - this.instruments.start( - function (err) { - if (err) return treatError(err, cb); - // instruments will never check into the command proxy, so go ahead - // and just call back here once instruments is started, rather than - // waiting for it to make the first connection to the command proxy - cb(); - } - , function () { - // ignore unexpected instruments exit since that's exactly what - // we're expecting anyway - }); - } else { - logger.debug("Starting command proxy."); - this.commandProxy.start( - function (err) { // on first connection - // first let instruments know so that it does not restart itself - this.instruments.launchHandler(err); - // then we call the callback - cb(err); - }.bind(this) - // - , function (err) { // regular cb - if (err) return treatError(err, cb); - logger.debug("Starting instruments"); - this.instruments.start( - function (err) { - if (err) return treatError(err, cb); - // we don't call cb here, waiting for first connection or error - }.bind(this) - , function (code) { + logger.debug("Starting command proxy."); + this.commandProxy.start( + function onFirstConnection(err) { + // first let instruments know so that it does not restart itself + this.instruments.launchHandler(err); + // then we call the callback + cb(err); + }.bind(this) + , function regularCallback(err) { + if (err) return treatError(err, cb); + logger.debug("Starting instruments"); + this.instruments.start( + function (err) { + if (err) return treatError(err, cb); + // we don't call cb here, waiting for first connection or error + }.bind(this) + , function (code) { + if (!this.shouldIgnoreInstrumentsExit()) { this.onUnexpectedInstrumentsExit(code); - }.bind(this) - ); - }.bind(this) - ); - } + } + }.bind(this) + ); + }.bind(this) + ); }; IOS.prototype.makeInstruments = function (cb) { @@ -379,7 +361,7 @@ IOS.prototype.makeInstruments = function (cb) { var bootstrap = prepareBootstrap({ sock: this.sock, interKeyDelay: this.args.interKeyDelay, - justLoopInfinitely: this.shouldIgnoreInstrumentsExit(), + justLoopInfinitely: false, autoAcceptAlerts: !(!this.args.autoAcceptAlerts || this.args.autoAcceptAlerts === 'false'), autoDismissAlerts: !(!this.args.autoDismissAlerts || this.args.autoDismissAlerts === 'false'), sendKeyStrategy: this.args.sendKeyStrategy || (this.args.udid ? 'grouped' : 'oneByOne') @@ -825,7 +807,7 @@ IOS.prototype.detectUdid = function (cb) { } if (stdout && stdout.length > 2) { - this.args.udid = stdout.replace("\n", ""); + this.args.udid = stdout.split("\n")[0]; logger.debug("Detected udid as " + this.args.udid); cb(); } else { diff --git a/lib/devices/ios/safari.js b/lib/devices/ios/safari.js index 6e5991649..c8ecf9155 100644 --- a/lib/devices/ios/safari.js +++ b/lib/devices/ios/safari.js @@ -5,8 +5,7 @@ var IOS = require('./ios.js') , path = require('path') , _ = require('underscore'); -var NATIVE_REAL_SAFARI_MIN_VER = 7.0 - , SAFARI_BUNDLE = 'com.apple.mobilesafari'; +var SAFARI_BUNDLE = 'com.apple.mobilesafari'; var Safari = function () { this.init(); @@ -58,6 +57,38 @@ Safari.prototype.moveBuiltInApp = function (cb) { } }; +// once safariLauncher is running and instrumented, this function +// finds the button which launches safari and clicks it. +Safari.prototype._clickButtonToLaunchSafari = function (cb) { + this.findElement('accessibility id', 'launch safari', + function (err, res) { + if (err || res.status !== 0) { + var msg = "Error. Could not find button to launch Safari. " + + "Make sure you are using the latest version of " + + "SafariLauncher that appium is using"; + logger.error(msg); + return cb(new Error(msg)); + } + + var buttonId = res.value.ELEMENT; + + this.click(buttonId, function (err, res) { + if (err || res.status !== 0) { + var msg = "Error. For whatever reason, could not click " + + "the 'launch safari' button of SafariLauncher"; + logger.error(msg); + return cb(new Error(msg)); + } + + logger.debug("Clicked button, safari should be launching."); + + // we're done with instruments at this point, we go on to Safari + this.navToInitialWebview(cb); + + }.bind(this)); + }.bind(this)); +}; + Safari.prototype._start = IOS.prototype.start; Safari.prototype.start = function (cb, onDie) { var newOnDie = function (err) { @@ -69,13 +100,23 @@ Safari.prototype.start = function (cb, onDie) { this._start(function (err) { if (err) return cb(err); - this.navToInitialWebview(cb); + + if (this.args.udid) { + logger.debug("On Safari Launcher. Tapping button to launch Safari"); + + this._clickButtonToLaunchSafari(function (err) { + if (err) return cb(err); + + this.navToInitialWebview(cb); + }.bind(this)); + } else { + this.navToInitialWebview(cb); + } }.bind(this), newOnDie); }; Safari.prototype.shouldIgnoreInstrumentsExit = function () { - return !!this.args.udid && - this.iOSSDKVersion < NATIVE_REAL_SAFARI_MIN_VER; + return !!this.args.udid; }; Safari.prototype._click = IOS.prototype.click; @@ -103,16 +144,6 @@ Safari.prototype.setInitialOrientation = function (cb) { this._setInitialOrientation(cb); }; -Safari.prototype._configureBootstrap = IOS.prototype.configureBootstrap; -Safari.prototype.configureBootstrap = function (cb) { - if (this.shouldIgnoreInstrumentsExit()) { - logger.debug("Not setting bootstrap config because we're on " + - "SafariLauncher"); - return cb(); - } - this._configureBootstrap(cb); -}; - Safari.prototype.installToRealDevice = function (cb) { if (this.args.udid) { try { diff --git a/package.json b/package.json index 913de09e7..2bc33830b 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "q": "~1.1.2", "request": "~2.53.0", "rimraf": "~2.2.8", + "safari-launcher": "=2.0.5", "sandboxed-module": "~2.0.0", "serve-favicon": "~2.2.0", "socket.io": "~1.3.4", diff --git a/reset.sh b/reset.sh index 97ede0f5e..1678d8f8a 100755 --- a/reset.sh +++ b/reset.sh @@ -206,23 +206,20 @@ reset_ios() { run_cmd "$grunt" buildApp:WebViewApp:iphonesimulator$sdk_ver fi if $should_reset_realsafari; then - echo "* Cloning/updating SafariLauncher" - run_cmd git submodule update --init submodules/SafariLauncher echo "* Building SafariLauncher for real devices" run_cmd rm -rf build/SafariLauncher run_cmd mkdir -p build/SafariLauncher - run_cmd rm -f submodules/SafariLauncher/target.xcconfig - touch submodules/SafariLauncher/target.xcconfig - echo "BUNDLE_ID = com.bytearc.SafariLauncher" >> submodules/SafariLauncher/target.xcconfig + touch build/SafariLauncher/target.xcconfig + echo "BUNDLE_ID = com.bytearc.SafariLauncher" >> build/SafariLauncher/target.xcconfig if [[ ! -z $code_sign_identity ]]; then - echo "IDENTITY_NAME = " $code_sign_identity >> submodules/SafariLauncher/target.xcconfig + echo "IDENTITY_NAME = " $code_sign_identity >> build/SafariLauncher/target.xcconfig else - echo "IDENTITY_NAME = iPhone Developer" >> submodules/SafariLauncher/target.xcconfig + echo "IDENTITY_NAME = iPhone Developer" >> build/SafariLauncher/target.xcconfig fi - echo "IDENTITY_CODE = " $provisioning_profile >> submodules/SafariLauncher/target.xcconfig - run_cmd "$grunt" buildSafariLauncherApp:iphoneos:"target.xcconfig" + echo "IDENTITY_CODE = " $provisioning_profile >> build/SafariLauncher/target.xcconfig + run_cmd "$grunt" buildSafariLauncherApp:iphoneos:"$appium_home/build/SafariLauncher/target.xcconfig" echo "* Copying SafariLauncher for real devices to build" - run_cmd zip -r build/SafariLauncher/SafariLauncher submodules/SafariLauncher/build/Release-iphoneos/SafariLauncher.app + run_cmd zip -r build/SafariLauncher/SafariLauncher node_modules/safari-launcher/build/Release-iphoneos/SafariLauncher.app fi echo "* Cloning/updating libimobiledevice-macosx" run_cmd git submodule update --init submodules/libimobiledevice-macosx diff --git a/submodules/SafariLauncher b/submodules/SafariLauncher deleted file mode 160000 index cc13a3597..000000000 --- a/submodules/SafariLauncher +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc13a359702b89e5c36f4b8c7fbfcd9ef705840a