Repository: cordova-medic
Updated Branches:
  refs/heads/master 4bd711ccc -> 73528ed96


Appium runner/CI improvements:

    Changed ios device in appium config to match the emulator on osx slave
    Added 'common' folder to the search paths for Appium runner
    Save appium log
    Pass helpers to tests
    Untied from mobilespec
    Extended wdHelper with getWebviewContext() function
    Added InjectLibraries function to wdHelper


Project: http://git-wip-us.apache.org/repos/asf/cordova-medic/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-medic/commit/73528ed9
Tree: http://git-wip-us.apache.org/repos/asf/cordova-medic/tree/73528ed9
Diff: http://git-wip-us.apache.org/repos/asf/cordova-medic/diff/73528ed9

Branch: refs/heads/master
Commit: 73528ed96409f2a4bc6a3389050e616b2f113bc8
Parents: 4bd711c
Author: Alexander Sorokin <[email protected]>
Authored: Thu Mar 31 12:17:30 2016 +0300
Committer: Alexander Sorokin <[email protected]>
Committed: Thu Mar 31 13:20:34 2016 +0300

----------------------------------------------------------------------
 buildbot-conf/cordova-config.json.sample |   4 +-
 buildbot-conf/cordova.conf               |   4 +
 lib/appium/helpers/lib/q.min.js          |   1 +
 lib/appium/helpers/screenshotHelper.js   |  57 ++++++++++++
 lib/appium/helpers/wdHelper.js           | 122 ++++++++++++++++++++++++++
 medic/medic-appium.js                    |  89 ++++++++++++-------
 6 files changed, 241 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/buildbot-conf/cordova-config.json.sample
----------------------------------------------------------------------
diff --git a/buildbot-conf/cordova-config.json.sample 
b/buildbot-conf/cordova-config.json.sample
index 40c167a..6200af0 100644
--- a/buildbot-conf/cordova-config.json.sample
+++ b/buildbot-conf/cordova-config.json.sample
@@ -12,8 +12,8 @@
     "appium": {
         "androidDeviceName":      "Galaxy_Nexus",
         "androidPlatformVersion": "19",
-        "iosDeviceName":          "iPhone 5",
-        "iosPlatformVersion":     "8.4",
+        "iosDeviceName":          "iPhone 6s",
+        "iosPlatformVersion":     "9.1",
         "timeout":                2400,
         "screenshotPath":         "appium_screenshots"
     },

http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/buildbot-conf/cordova.conf
----------------------------------------------------------------------
diff --git a/buildbot-conf/cordova.conf b/buildbot-conf/cordova.conf
index d66cb07..207cf38 100644
--- a/buildbot-conf/cordova.conf
+++ b/buildbot-conf/cordova.conf
@@ -52,6 +52,7 @@ IOS_APPIUM_NAME         = 
medic_config['appium']['iosDeviceName']
 IOS_APPIUM_PLATFORM     = medic_config['appium']['iosPlatformVersion']
 APPIUM_RUN_TIMEOUT      = medic_config['appium']['timeout']
 APPIUM_SCREENSHOT_PATH  = medic_config['appium']['screenshotPath']
+APPIUM_LOG_FILE_NAME    = 'appium.log'
 LOG_GETTING_TIMEOUT     = 30 # in seconds
 TEST_SUMMARY_FILE_NAME  = 'test_summary.json'
 MASTER_HOSTNAME         = socket.gethostname()
@@ -253,6 +254,7 @@ CORDOVA_STEPS_SET_SETTINGS = [
 
     Set('build_id',          I('%(prop:buildername)s-%(prop:buildnumber)s-' + 
MASTER_HOSTNAME)),
     Set('test_summary_file', I('%(prop:builddir)s/' + TEST_SUMMARY_FILE_NAME)),
+    Set('appium_log_file',   I('%(prop:builddir)s/' + APPIUM_LOG_FILE_NAME)),
 
     Set('npm_cache_dir',  I('%(prop:builddir)s/' + NPM_CACHE_DIR_NAME)),
     Set('npm_temp_dir',   I('%(prop:builddir)s/' + NPM_TEMP_DIR_NAME)),
@@ -424,12 +426,14 @@ def cordova_steps_run_appium(platform):
                     '--platformVersion', APPIUM_PLATFORM,
                     '--plugins', pluginsString,
                     '--screenshotPath', APPIUM_SCREENSHOT_PATH,
+                    '--logFile', P('appium_log_file'),
                 ],
                 description='running Appium tests',
                 timeout = APPIUM_RUN_TIMEOUT,
                 haltOnFailure = False,
                 flunkOnFailure = False,
             ),
+            SH(command=['cat', P('appium_log_file')], description='getting 
Appium server logs'),
         ]
     return []
 

http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/lib/appium/helpers/lib/q.min.js
----------------------------------------------------------------------
diff --git a/lib/appium/helpers/lib/q.min.js b/lib/appium/helpers/lib/q.min.js
new file mode 100644
index 0000000..cd7c65d
--- /dev/null
+++ b/lib/appium/helpers/lib/q.min.js
@@ -0,0 +1 @@
+!function(t){"use strict";if("function"==typeof 
bootstrap)bootstrap("promise",t);else if("object"==typeof 
exports&&"object"==typeof module)module.exports=t();else if("function"==typeof 
define&&define.amd)define(t);else if("undefined"!=typeof 
ses){if(!ses.ok())return;ses.makeQ=t}else{if("undefined"==typeof 
window&&"undefined"==typeof self)throw new Error("This environment was not 
anticipated by Q. Please file a bug.");var n="undefined"!=typeof 
window?window:self,e=n.Q;n.Q=t(),n.Q.noConflict=function(){return 
n.Q=e,this}}}(function(){"use strict";function t(t){return function(){return 
K.apply(t,arguments)}}function n(t){return t===Object(t)}function 
e(t){return"[object StopIteration]"===en(t)||t instanceof _}function 
r(t,n){if(V&&n.stack&&"object"==typeof 
t&&null!==t&&t.stack&&-1===t.stack.indexOf(rn)){for(var 
e=[],r=n;r;r=r.source)r.stack&&e.unshift(r.stack);e.unshift(t.stack);var 
i=e.join("\n"+rn+"\n");t.stack=o(i)}}function o(t){for(var 
n=t.split("\n"),e=[],r=0;r<n.length;++r){var 
 o=n[r];c(o)||i(o)||!o||e.push(o)}return e.join("\n")}function 
i(t){return-1!==t.indexOf("(module.js:")||-1!==t.indexOf("(node.js:")}function 
u(t){var n=/at .+ 
\((.+):(\d+):(?:\d+)\)$/.exec(t);if(n)return[n[1],Number(n[2])];var e=/at ([^ 
]+):(\d+):(?:\d+)$/.exec(t);if(e)return[e[1],Number(e[2])];var 
r=/.*@(.+):(\d+)$/.exec(t);return r?[r[1],Number(r[2])]:void 0}function 
c(t){var n=u(t);if(!n)return!1;var e=n[0],r=n[1];return 
e===H&&r>=q&&fn>=r}function s(){if(V)try{throw new Error}catch(t){var 
n=t.stack.split("\n"),e=n[0].indexOf("@")>0?n[1]:n[2],r=u(e);if(!r)return;return
 H=r[0],r[1]}}function f(t,n,e){return function(){return"undefined"!=typeof 
console&&"function"==typeof console.warn&&console.warn(n+" is deprecated, use 
"+e+" instead.",new Error("").stack),t.apply(t,arguments)}}function p(t){return 
t instanceof h?t:g(t)?O(t):E(t)}function a(){function 
t(t){n=t,i.source=t,W(e,function(n,e){p.nextTick(function(){t.promiseDispatch.apply(t,e)})},void
 0),e=void 0,r=void 0}var n,e=[],r=
 [],o=Z(a.prototype),i=Z(h.prototype);if(i.promiseDispatch=function(t,o,i){var 
u=L(arguments);e?(e.push(u),"when"===o&&i[1]&&r.push(i[1])):p.nextTick(function(){n.promiseDispatch.apply(n,u)})},i.valueOf=function(){if(e)return
 i;var t=v(n);return m(t)&&(n=t),t},i.inspect=function(){return 
n?n.inspect():{state:"pending"}},p.longStackSupport&&V)try{throw new 
Error}catch(u){i.stack=u.stack.substring(u.stack.indexOf("\n")+1)}return 
o.promise=i,o.resolve=function(e){n||t(p(e))},o.fulfill=function(e){n||t(E(e))},o.reject=function(e){n||t(R(e))},o.notify=function(t){n||W(r,function(n,e){p.nextTick(function(){e(t)})},void
 0)},o}function l(t){if("function"!=typeof t)throw new TypeError("resolver must 
be a function.");var 
n=a();try{t(n.resolve,n.reject,n.notify)}catch(e){n.reject(e)}return 
n.promise}function d(t){return l(function(n,e){for(var 
r=0,o=t.length;o>r;r++)p(t[r]).then(n,e)})}function h(t,n,e){void 
0===n&&(n=function(t){return R(new Error("Promise does not support operation: 
"+t))}),v
 oid 0===e&&(e=function(){return{state:"unknown"}});var 
r=Z(h.prototype);if(r.promiseDispatch=function(e,o,i){var 
u;try{u=t[o]?t[o].apply(r,i):n.call(r,o,i)}catch(c){u=R(c)}e&&e(u)},r.inspect=e,e){var
 o=e();"rejected"===o.state&&(r.exception=o.reason),r.valueOf=function(){var 
t=e();return"pending"===t.state||"rejected"===t.state?r:t.value}}return 
r}function y(t,n,e,r){return p(t).then(n,e,r)}function v(t){if(m(t)){var 
n=t.inspect();if("fulfilled"===n.state)return n.value}return t}function 
m(t){return t instanceof h}function g(t){return n(t)&&"function"==typeof 
t.then}function k(t){return m(t)&&"pending"===t.inspect().state}function 
j(t){return!m(t)||"fulfilled"===t.inspect().state}function w(t){return 
m(t)&&"rejected"===t.inspect().state}function 
b(){on.length=0,un.length=0,sn||(sn=!0)}function x(t,n){sn&&("object"==typeof 
process&&"function"==typeof 
process.emit&&p.nextTick.runAfter(function(){-1!==X(un,t)&&(process.emit("unhandledRejection",n,t),cn.push(t))}),un.push(t),on.push(n&&
 "undefined"!=typeof n.stack?n.stack:"(no stack) "+n))}function T(t){if(sn){var 
n=X(un,t);-1!==n&&("object"==typeof process&&"function"==typeof 
process.emit&&p.nextTick.runAfter(function(){var 
e=X(cn,t);-1!==e&&(process.emit("rejectionHandled",on[n],t),cn.splice(e,1))}),un.splice(n,1),on.splice(n,1))}}function
 R(t){var n=h({when:function(n){return 
n&&T(this),n?n(t):this}},function(){return 
this},function(){return{state:"rejected",reason:t}});return x(n,t),n}function 
E(t){return h({when:function(){return t},get:function(n){return 
t[n]},set:function(n,e){t[n]=e},"delete":function(n){delete 
t[n]},post:function(n,e){return null===n||void 0===n?t.apply(void 
0,e):t[n].apply(t,e)},apply:function(n,e){return 
t.apply(n,e)},keys:function(){return nn(t)}},void 
0,function(){return{state:"fulfilled",value:t}})}function O(t){var n=a();return 
p.nextTick(function(){try{t.then(n.resolve,n.reject,n.notify)}catch(e){n.reject(e)}}),n.promise}function
 S(t){return h({isDef:function(){}},function(n,e){retu
 rn A(t,n,e)},function(){return p(t).inspect()})}function N(t,n,e){return 
p(t).spread(n,e)}function D(t){return function(){function n(t,n){var 
u;if("undefined"==typeof StopIteration){try{u=r[t](n)}catch(c){return 
R(c)}return u.done?p(u.value):y(u.value,o,i)}try{u=r[t](n)}catch(c){return 
e(c)?p(c.value):R(c)}return y(u,o,i)}var 
r=t.apply(this,arguments),o=n.bind(n,"next"),i=n.bind(n,"throw");return 
o()}}function P(t){p.done(p.async(t)())}function C(t){throw new _(t)}function 
Q(t){return function(){return N([this,I(arguments)],function(n,e){return 
t.apply(n,e)})}}function A(t,n,e){return p(t).dispatch(n,e)}function 
I(t){return y(t,function(t){var n=0,e=a();return W(t,function(r,o,i){var 
u;m(o)&&"fulfilled"===(u=o.inspect()).state?t[i]=u.value:(++n,y(o,function(r){t[i]=r,0===--n&&e.resolve(t)},e.reject,function(t){e.notify({index:i,value:t})}))},void
 0),0===n&&e.resolve(t),e.promise})}function U(t){if(0===t.length)return 
p.resolve();var n=p.defer(),e=0;return W(t,function(r,o,i){functio
 n u(t){n.resolve(t)}function c(){e--,0===e&&n.reject(new Error("Can't get 
fulfillment value from any promise, all promises were rejected."))}function 
s(t){n.notify({index:i,value:t})}var f=t[i];e++,y(f,u,c,s)},void 
0),n.promise}function F(t){return y(t,function(t){return 
t=Y(t,p),y(I(Y(t,function(t){return y(t,z,z)})),function(){return 
t})})}function M(t){return p(t).allSettled()}function B(t,n){return 
p(t).then(void 0,void 0,n)}function $(t,n){return p(t).nodeify(n)}var 
V=!1;try{throw new Error}catch(G){V=!!G.stack}var 
H,_,q=s(),z=function(){},J=function(){function t(){for(var 
t,r;e.next;)e=e.next,t=e.task,e.task=void 0,r=e.domain,r&&(e.domain=void 
0,r.enter()),n(t,r);for(;c.length;)t=c.pop(),n(t);o=!1}function 
n(n,e){try{n()}catch(r){if(u)throw 
e&&e.exit(),setTimeout(t,0),e&&e.enter(),r;setTimeout(function(){throw 
r},0)}e&&e.exit()}var e={task:void 0,next:null},r=e,o=!1,i=void 
0,u=!1,c=[];if(J=function(t){r=r.next={task:t,domain:u&&process.domain,next:null},o||(o=!0,i())},"object"
 ==typeof process&&"[object 
process]"===process.toString()&&process.nextTick)u=!0,i=function(){process.nextTick(t)};else
 if("function"==typeof setImmediate)i="undefined"!=typeof 
window?setImmediate.bind(window,t):function(){setImmediate(t)};else 
if("undefined"!=typeof MessageChannel){var s=new 
MessageChannel;s.port1.onmessage=function(){i=f,s.port1.onmessage=t,t()};var 
f=function(){s.port2.postMessage(0)};i=function(){setTimeout(t,0),f()}}else 
i=function(){setTimeout(t,0)};return 
J.runAfter=function(t){c.push(t),o||(o=!0,i())},J}(),K=Function.call,L=t(Array.prototype.slice),W=t(Array.prototype.reduce||function(t,n){var
 e=0,r=this.length;if(1===arguments.length)for(;;){if(e in 
this){n=this[e++];break}if(++e>=r)throw new TypeError}for(;r>e;e++)e in 
this&&(n=t(n,this[e],e));return 
n}),X=t(Array.prototype.indexOf||function(t){for(var 
n=0;n<this.length;n++)if(this[n]===t)return 
n;return-1}),Y=t(Array.prototype.map||function(t,n){var e=this,r=[];return 
W(e,function(o,i,u){r.push(t.call(n,i
 ,u,e))},void 0),r}),Z=Object.create||function(t){function n(){}return 
n.prototype=t,new 
n},tn=t(Object.prototype.hasOwnProperty),nn=Object.keys||function(t){var 
n=[];for(var e in t)tn(t,e)&&n.push(e);return 
n},en=t(Object.prototype.toString);_="undefined"!=typeof 
ReturnValue?ReturnValue:function(t){this.value=t};var rn="From previous 
event:";p.resolve=p,p.nextTick=J,p.longStackSupport=!1,"object"==typeof 
process&&process&&process.env&&process.env.Q_DEBUG&&(p.longStackSupport=!0),p.defer=a,a.prototype.makeNodeResolver=function(){var
 t=this;return 
function(n,e){n?t.reject(n):t.resolve(arguments.length>2?L(arguments,1):e)}},p.Promise=l,p.promise=l,l.race=d,l.all=I,l.reject=R,l.resolve=p,p.passByCopy=function(t){return
 t},h.prototype.passByCopy=function(){return this},p.join=function(t,n){return 
p(t).join(n)},h.prototype.join=function(t){return 
p([this,t]).spread(function(t,n){if(t===n)return t;throw new Error("Can't join: 
not the same: "+t+" "+n)})},p.race=d,h.prototype.race=function()
 {return 
this.then(p.race)},p.makePromise=h,h.prototype.toString=function(){return"[object
 Promise]"},h.prototype.then=function(t,n,e){function 
o(n){try{return"function"==typeof t?t(n):n}catch(e){return R(e)}}function 
i(t){if("function"==typeof n){r(t,c);try{return n(t)}catch(e){return 
R(e)}}return R(t)}function u(t){return"function"==typeof e?e(t):t}var 
c=this,s=a(),f=!1;return 
p.nextTick(function(){c.promiseDispatch(function(t){f||(f=!0,s.resolve(o(t)))},"when",[function(t){f||(f=!0,s.resolve(i(t)))}])}),c.promiseDispatch(void
 0,"when",[void 0,function(t){var 
n,e=!1;try{n=u(t)}catch(r){if(e=!0,!p.onerror)throw 
r;p.onerror(r)}e||s.notify(n)}]),s.promise},p.tap=function(t,n){return 
p(t).tap(n)},h.prototype.tap=function(t){return 
t=p(t),this.then(function(n){return 
t.fcall(n).thenResolve(n)})},p.when=y,h.prototype.thenResolve=function(t){return
 this.then(function(){return t})},p.thenResolve=function(t,n){return 
p(t).thenResolve(n)},h.prototype.thenReject=function(t){return this.then(f
 unction(){throw t})},p.thenReject=function(t,n){return 
p(t).thenReject(n)},p.nearer=v,p.isPromise=m,p.isPromiseAlike=g,p.isPending=k,h.prototype.isPending=function(){return"pending"===this.inspect().state},p.isFulfilled=j,h.prototype.isFulfilled=function(){return"fulfilled"===this.inspect().state},p.isRejected=w,h.prototype.isRejected=function(){return"rejected"===this.inspect().state};var
 
on=[],un=[],cn=[],sn=!0;p.resetUnhandledRejections=b,p.getUnhandledReasons=function(){return
 
on.slice()},p.stopUnhandledRejectionTracking=function(){b(),sn=!1},b(),p.reject=R,p.fulfill=E,p.master=S,p.spread=N,h.prototype.spread=function(t,n){return
 this.all().then(function(n){return t.apply(void 
0,n)},n)},p.async=D,p.spawn=P,p["return"]=C,p.promised=Q,p.dispatch=A,h.prototype.dispatch=function(t,n){var
 e=this,r=a();return 
p.nextTick(function(){e.promiseDispatch(r.resolve,t,n)}),r.promise},p.get=function(t,n){return
 p(t).dispatch("get",[n])},h.prototype.get=function(t){return 
this.dispatch("get",[t
 ])},p.set=function(t,n,e){return 
p(t).dispatch("set",[n,e])},h.prototype.set=function(t,n){return 
this.dispatch("set",[t,n])},p.del=p["delete"]=function(t,n){return 
p(t).dispatch("delete",[n])},h.prototype.del=h.prototype["delete"]=function(t){return
 this.dispatch("delete",[t])},p.mapply=p.post=function(t,n,e){return 
p(t).dispatch("post",[n,e])},h.prototype.mapply=h.prototype.post=function(t,n){return
 this.dispatch("post",[t,n])},p.send=p.mcall=p.invoke=function(t,n){return 
p(t).dispatch("post",[n,L(arguments,2)])},h.prototype.send=h.prototype.mcall=h.prototype.invoke=function(t){return
 this.dispatch("post",[t,L(arguments,1)])},p.fapply=function(t,n){return 
p(t).dispatch("apply",[void 0,n])},h.prototype.fapply=function(t){return 
this.dispatch("apply",[void 0,t])},p["try"]=p.fcall=function(t){return 
p(t).dispatch("apply",[void 
0,L(arguments,1)])},h.prototype.fcall=function(){return 
this.dispatch("apply",[void 0,L(arguments)])},p.fbind=function(t){var 
n=p(t),e=L(arguments,1);return fu
 nction(){return 
n.dispatch("apply",[this,e.concat(L(arguments))])}},h.prototype.fbind=function(){var
 t=this,n=L(arguments);return function(){return 
t.dispatch("apply",[this,n.concat(L(arguments))])}},p.keys=function(t){return 
p(t).dispatch("keys",[])},h.prototype.keys=function(){return 
this.dispatch("keys",[])},p.all=I,h.prototype.all=function(){return 
I(this)},p.any=U,h.prototype.any=function(){return 
U(this)},p.allResolved=f(F,"allResolved","allSettled"),h.prototype.allResolved=function(){return
 F(this)},p.allSettled=M,h.prototype.allSettled=function(){return 
this.then(function(t){return I(Y(t,function(t){function n(){return 
t.inspect()}return 
t=p(t),t.then(n,n)}))})},p.fail=p["catch"]=function(t,n){return p(t).then(void 
0,n)},h.prototype.fail=h.prototype["catch"]=function(t){return this.then(void 
0,t)},p.progress=B,h.prototype.progress=function(t){return this.then(void 
0,void 0,t)},p.fin=p["finally"]=function(t,n){return 
p(t)["finally"](n)},h.prototype.fin=h.prototype["finally"]=
 function(t){return t=p(t),this.then(function(n){return 
t.fcall().then(function(){return n})},function(n){return 
t.fcall().then(function(){throw n})})},p.done=function(t,n,e,r){return 
p(t).done(n,e,r)},h.prototype.done=function(t,n,e){var 
o=function(t){p.nextTick(function(){if(r(t,i),!p.onerror)throw 
t;p.onerror(t)})},i=t||n||e?this.then(t,n,e):this;"object"==typeof 
process&&process&&process.domain&&(o=process.domain.bind(o)),i.then(void 
0,o)},p.timeout=function(t,n,e){return 
p(t).timeout(n,e)},h.prototype.timeout=function(t,n){var 
e=a(),r=setTimeout(function(){n&&"string"!=typeof n||(n=new Error(n||"Timed out 
after "+t+" ms"),n.code="ETIMEDOUT"),e.reject(n)},t);return 
this.then(function(t){clearTimeout(r),e.resolve(t)},function(t){clearTimeout(r),e.reject(t)},e.notify),e.promise},p.delay=function(t,n){return
 void 0===n&&(n=t,t=void 0),p(t).delay(n)},h.prototype.delay=function(t){return 
this.then(function(n){var e=a();return 
setTimeout(function(){e.resolve(n)},t),e.promise})},p.nfapp
 ly=function(t,n){return p(t).nfapply(n)},h.prototype.nfapply=function(t){var 
n=a(),e=L(t);return 
e.push(n.makeNodeResolver()),this.fapply(e).fail(n.reject),n.promise},p.nfcall=function(t){var
 n=L(arguments,1);return p(t).nfapply(n)},h.prototype.nfcall=function(){var 
t=L(arguments),n=a();return 
t.push(n.makeNodeResolver()),this.fapply(t).fail(n.reject),n.promise},p.nfbind=p.denodeify=function(t){var
 n=L(arguments,1);return function(){var e=n.concat(L(arguments)),r=a();return 
e.push(r.makeNodeResolver()),p(t).fapply(e).fail(r.reject),r.promise}},h.prototype.nfbind=h.prototype.denodeify=function(){var
 t=L(arguments);return t.unshift(this),p.denodeify.apply(void 
0,t)},p.nbind=function(t,n){var e=L(arguments,2);return function(){function 
r(){return t.apply(n,arguments)}var o=e.concat(L(arguments)),i=a();return 
o.push(i.makeNodeResolver()),p(r).fapply(o).fail(i.reject),i.promise}},h.prototype.nbind=function(){var
 t=L(arguments,0);return t.unshift(this),p.nbind.apply(void 0,t)},p.nmapply=p
 .npost=function(t,n,e){return 
p(t).npost(n,e)},h.prototype.nmapply=h.prototype.npost=function(t,n){var 
e=L(n||[]),r=a();return 
e.push(r.makeNodeResolver()),this.dispatch("post",[t,e]).fail(r.reject),r.promise},p.nsend=p.nmcall=p.ninvoke=function(t,n){var
 e=L(arguments,2),r=a();return 
e.push(r.makeNodeResolver()),p(t).dispatch("post",[n,e]).fail(r.reject),r.promise},h.prototype.nsend=h.prototype.nmcall=h.prototype.ninvoke=function(t){var
 n=L(arguments,1),e=a();return 
n.push(e.makeNodeResolver()),this.dispatch("post",[t,n]).fail(e.reject),e.promise},p.nodeify=$,h.prototype.nodeify=function(t){return
 t?void 
this.then(function(n){p.nextTick(function(){t(null,n)})},function(n){p.nextTick(function(){t(n)})}):this},p.noConflict=function(){throw
 new Error("Q.noConflict only works when Q is used as a global")};var 
fn=s();return p});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/lib/appium/helpers/screenshotHelper.js
----------------------------------------------------------------------
diff --git a/lib/appium/helpers/screenshotHelper.js 
b/lib/appium/helpers/screenshotHelper.js
new file mode 100644
index 0000000..dab6d75
--- /dev/null
+++ b/lib/appium/helpers/screenshotHelper.js
@@ -0,0 +1,57 @@
+/* jshint node: true */
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+'use strict';
+
+var path = require('path');
+
+function generateScreenshotName() {
+    var date = new Date();
+
+    var month = date.getMonth() + 1;
+    var day = date.getDate();
+    var hour = date.getHours();
+    var min = date.getMinutes();
+    var sec = date.getSeconds();
+
+    month = (month < 10 ? "0" : "") + month;
+    day = (day < 10 ? "0" : "") + day;
+    hour = (hour < 10 ? "0" : "") + hour;
+    min = (min < 10 ? "0" : "") + min;
+    sec = (sec < 10 ? "0" : "") + sec;
+
+    return date.getFullYear() + '-' + month + '-' + day + '_' +  hour + '.' + 
min + '.' + sec + '.png';
+}
+
+module.exports.saveScreenshot = function (driver) {
+    var oldContext;
+    return driver
+        .currentContext()
+        .then(function (cc) {
+            oldContext = cc;
+        })
+        .context('NATIVE_APP')
+        .saveScreenshot(path.join(global.SCREENSHOT_PATH, 
generateScreenshotName()))
+        .then(function () {
+            return driver.context(oldContext);
+        });
+};

http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/lib/appium/helpers/wdHelper.js
----------------------------------------------------------------------
diff --git a/lib/appium/helpers/wdHelper.js b/lib/appium/helpers/wdHelper.js
new file mode 100644
index 0000000..967d7c9
--- /dev/null
+++ b/lib/appium/helpers/wdHelper.js
@@ -0,0 +1,122 @@
+/* jshint node: true */
+/* global navigator */
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+'use strict';
+
+var APPIUM_SERVER_HOST = 'localhost';
+var APPIUM_SERVER_PORT = 4723;
+var WEBVIEW_WAIT_TIMEOUT = 5000;
+var IMPLICIT_WAIT_TIMEOUT = 10000;
+
+var fs = require('fs');
+var path = require('path');
+
+module.exports.getDriver = function (platform) {
+    var normalizedPlatform;
+    switch (platform.toLowerCase()) {
+        case 'android':
+            normalizedPlatform = 'Android';
+            break;
+        case 'ios':
+            normalizedPlatform = 'iOS';
+            break;
+        default:
+            throw 'Unknown platform: ' + platform;
+    }
+
+    var serverConfig = {
+        host: APPIUM_SERVER_HOST,
+        port: APPIUM_SERVER_PORT
+    };
+
+    var driverConfig = {
+        browserName: '',
+        'appium-version': '1.5',
+        platformName: normalizedPlatform,
+        platformVersion: global.PLATFORM_VERSION || '',
+        deviceName: global.DEVICE_NAME || '',
+        app: global.PACKAGE_PATH,
+        autoAcceptAlerts: true,
+    };
+
+    var driver = global.WD.promiseChainRemote(serverConfig);
+    module.exports.configureLogging(driver);
+
+    return driver
+        .init(driverConfig)
+        .setImplicitWaitTimeout(IMPLICIT_WAIT_TIMEOUT);
+};
+
+module.exports.getWD = function () {
+    return global.WD;
+};
+
+module.exports.getWebviewContext = function (driver, retries) {
+    if (typeof retries === 'undefined') {
+        retries = 2;
+    }
+    return driver
+        .contexts()
+        .then(function (contexts) {
+            // take the last webview context
+            for (var i = 0; i < contexts.length; i++) {
+                if (contexts[i].indexOf('WEBVIEW') >= 0) {
+                    return contexts[i];
+                }
+            }
+            // no webview context, the app is still loading
+            return driver
+                .then(function () {
+                    if (retries > 0) {
+                        console.log('Couldn\'t get webview context. Retries 
remaining: ' + retries);
+                        return driver
+                            .sleep(WEBVIEW_WAIT_TIMEOUT)
+                            .then(function () {
+                                return 
module.exports.getWebviewContext(driver, retries - 1);
+                        });
+                    }
+                    throw 'Couldn\'t get webview context. Failing...';
+                });
+        });
+};
+
+module.exports.injectLibraries = function (driver) {
+    var q = fs.readFileSync(path.join(__dirname, '/lib/q.min.js'), 'utf8');
+    return driver
+        .execute(q)
+        .execute(function () {
+            navigator._appiumPromises = {};
+        }, []);
+};
+
+module.exports.configureLogging = function (driver) {
+    driver.on('status', function (info) {
+        console.log(info);
+    });
+    driver.on('command', function (meth, path, data) {
+        console.log(' > ' + meth, path, data || '');
+    });
+    driver.on('http', function (meth, path, data) {
+        console.log(' > ' + meth, path, data || '');
+    });
+};

http://git-wip-us.apache.org/repos/asf/cordova-medic/blob/73528ed9/medic/medic-appium.js
----------------------------------------------------------------------
diff --git a/medic/medic-appium.js b/medic/medic-appium.js
index 20afe52..1097b82 100644
--- a/medic/medic-appium.js
+++ b/medic/medic-appium.js
@@ -35,18 +35,20 @@
 // Run on Android emulator:
 // node cordova-medic/medic/medic.js appium --platform android --device-name 
appium --platform-version "21" -app mobilespec
 
-var fs              = require("fs");
-var path            = require("path");
-var util            = require("../lib/util");
-var MedicReporter   = require("../lib/MedicReporter");
-var optimist        = require("optimist");
-var kill            = require("tree-kill");
-var child_process   = require("child_process");
-var wd              = require("wd");
-var et              = require("expect-telnet");
-var shell           = require("shelljs");
-var Jasmine         = require("jasmine");
-var unorm           = require("unorm");
+var fs               = require("fs");
+var path             = require("path");
+var util             = require("../lib/util");
+var MedicReporter    = require("../lib/MedicReporter");
+var wd               = require("wd");
+var wdHelper         = require("../lib/appium/helpers/wdHelper");
+var screenshotHelper = require("../lib/appium/helpers/screenshotHelper");
+var optimist         = require("optimist");
+var kill             = require("tree-kill");
+var child_process    = require("child_process");
+var et               = require("expect-telnet");
+var shell            = require("shelljs");
+var Jasmine          = require("jasmine");
+var unorm            = require("unorm");
 
 var DEFAULT_APP_PATH = "mobilespec";
 var DEFAULT_IOS_DEVICE_NAME = "iPhone 5";
@@ -71,10 +73,17 @@ function getPackagePath(options) {
     case "android":
         return path.join(fullAppPath, 
"/platforms/android/build/outputs/apk/android-debug.apk");
     case "ios":
-        if (options.device) {
-            return path.join(fullAppPath, 
"/platforms/ios/build/device/mobilespec.ipa");
+        var searchDir = options.device ?
+            path.join(getFullAppPath(options.appPath), 
"/platforms/ios/build/device/") :
+            path.join(getFullAppPath(options.appPath), 
"/platforms/ios/build/emulator/");
+        var fileMask = options.device ? "*.ipa" : "*.app";
+        var files = shell.ls(searchDir + fileMask);
+        util.medicLog("Looking for app package in " + searchDir);
+        if (files && files.length > 0) {
+            util.medicLog("Found app package: " + files[0]);
+            return files[0];
         }
-        return path.join(fullAppPath, 
"/platforms/ios/build/emulator/mobilespec.app");
+        util.fatal("Could not find the app package");
     }
 }
 
@@ -97,14 +106,15 @@ function parseArgs() {
             .describe("app", "Path to the test app.")
             .default("udid", "")
             .describe("udid", "UDID of the ios device. Only needed when 
running tests on real iOS devices.")
-            .default("deviceName", null)
-            .describe("deviceName", "Name of the device to run tests on.")
-            .default("platformVersion", null)
+            .demand("deviceName")
+            .describe("deviceName", "Name of the device/avd/simulator to run 
tests on.")
+            .demand("platformVersion")
             .describe("platformVersion", "Version of the OS installed on the 
device or the emulator. For example, '21' for Android or '8.1' for iOS.")
             .default("output", path.join(__dirname, "../../test_summary.json"))
             .describe("output", "A file that will store test results")
             .describe("plugins", "A space-separated list of plugins to test.")
             .describe("screenshotPath", "A directory to save screenshots to, 
either absolute or relative to the directory containing cordova-medic.")
+            .describe("logFile", "A file to output Appium logs to.")
             .argv;
 
     // filling out the options object
@@ -114,7 +124,12 @@ function parseArgs() {
     options.appiumPlatformVersion = argv.platformVersion || 
DEFAULT_PLATFORM_VERSION;
     options.udid = argv.udid;
     options.device = argv.device;
-    options.outputPath = argv.output;
+    if (argv.output) {
+        options.outputPath = path.normalize(argv.output);
+    }
+    if (argv.logFile) {
+        options.logFile = path.normalize(argv.logFile);
+    }
     if (argv.screenshotPath) {
         if (path.isAbsolute(argv.screenshotPath)){
             options.screenshotPath = path.normalize(argv.screenshotPath);
@@ -137,13 +152,15 @@ function parseArgs() {
 
     // looking for the tests
     options.testPaths = [];
+    var searchPaths = [];
     options.pluginRepos.forEach(function (pluginRepo) {
-        var testPath = path.join(pluginRepo, "appium-tests", options.platform);
-        if (fs.existsSync(testPath)) {
-            util.medicLog("Found tests in: " + testPath);
-            options.testPaths.push(path.join(testPath, "*.spec.js"));
-        } else {
-            util.medicLog("Couldn't find tests in: " + testPath);
+        searchPaths.push(path.join(pluginRepo, "appium-tests", 
options.platform));
+        searchPaths.push(path.join(pluginRepo, "appium-tests", "common"));
+    });
+    searchPaths.forEach(function (searchPath) {
+        if (fs.existsSync(searchPath)) {
+            util.medicLog("Found tests in: " + searchPath);
+            options.testPaths.push(path.join(searchPath, "*.spec.js"));
         }
     });
 
@@ -176,16 +193,16 @@ function parseArgs() {
 
     // setting up the global variables so the tests could use them
     global.WD = wd;
+    global.WD_HELPER = wdHelper;
+    global.SCREENSHOT_HELPER = screenshotHelper;
     global.ET = et;
     global.SHELL = shell;
     global.DEVICE = options.device;
+    global.PLATFORM = options.platform;
     global.PLATFORM_VERSION = options.appiumPlatformVersion;
     global.DEVICE_NAME = options.appiumDeviceName;
     global.SCREENSHOT_PATH = options.screenshotPath;
-    if (options.platform === "ios") {
-        global.unorm = unorm;
-    }
-    global.PACKAGE_PATH = getPackagePath(options);
+    global.UNORM = unorm;
 
     // creating a directory to save screenshots to
     fs.stat(global.SCREENSHOT_PATH, function (err) {
@@ -197,9 +214,10 @@ function parseArgs() {
     return options;
 }
 
-function getLocalCLI() {
-    if (util.isWindows()) {
-        return "cordova.bat";
+function getLocalCLI(appPath) {
+    if (util.isWindows() || !fs.existsSync(path.join(getFullAppPath(appPath), 
"./cordova"))) {
+        // fall back to globally installed cordova if the app is not mobilespec
+        return "cordova";
     }
     return "./cordova";
 }
@@ -208,7 +226,7 @@ function getLocalCLI() {
 function prepareApp(options, callback) {
     var fullAppPath = getFullAppPath(options.appPath);
     var deviceString = options.device ? " --device" : "";
-    var buildCommand = getLocalCLI() + " build " + options.platform + 
deviceString;
+    var buildCommand = getLocalCLI(options.appPath) + " build " + 
options.platform + deviceString;
 
     // remove medic.json and (re)build
     shell.rm(path.join(fullAppPath, "www", "medic.json"));
@@ -221,6 +239,7 @@ function prepareApp(options, callback) {
                 if (error) {
                     util.fatal("Couldn't build the app: " + error);
                 } else {
+                    global.PACKAGE_PATH = getPackagePath(options);
                     callback();
                 }
             });
@@ -239,7 +258,6 @@ function killProcess(procObj, killSignal, callback) {
     if (procObj.alive) {
         procObj.alive = false;
         setTimeout(function () {
-            util.medicLog("Killing ios proxy...");
             kill(procObj.process.pid, killSignal, callback);
         }, 1000);
     } else {
@@ -387,6 +405,9 @@ function startAppiumServer(options, callback) {
     default:
         throw new Error("Unsupported platform: " + options.platform);
     }
+    if (options.logFile) {
+        additionalArgs += " --log " + options.logFile;
+    }
 
     appiumServerCommand = "node " + APPIUM_SERVER_PATH +
         " --address " + APPIUM_IP_ADDRESS +


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to