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]