Added new layer for iOS abstraction.

This commit is contained in:
Sebastian Tiedtke 2013-01-14 19:38:54 -08:00
Родитель 6db5be8069
Коммит 4c5583d450
5 изменённых файлов: 138 добавлений и 91 удалений

Просмотреть файл

@ -1,20 +1,15 @@
// Appium webserver controller methods
// https://github.com/hugs/appium/blob/master/appium/appium.py
var routing = require('./routing')
, path = require('path')
, rimraf = require('rimraf')
, instruments = require('../instruments/instruments');
, ios = require('./ios');
var Appium = function(app, udid, verbose, removeTraceDir) {
this.app = app;
this.udid = udid;
this.verbose = verbose;
this.instruments = null;
var Appium = function(args) {
this.args = args;
this.rest = null;
this.queue = [];
this.progress = 0;
this.devices = {};
this.active = null;
this.device = null;
this.sessionId = null;
this.removeTraceDir = removeTraceDir;
};
Appium.prototype.attachTo = function(rest, cb) {
@ -33,91 +28,43 @@ Appium.prototype.start = function(cb) {
this.sessionId = new Date().getTime();
console.log('Creating new appium session ' + this.sessionId);
if (this.instruments === null) {
this.instruments = instruments(
this.rest
, path.resolve(__dirname, '../' + this.app)
, this.udid
, path.resolve(__dirname, 'uiauto/bootstrap.js')
, path.resolve(__dirname, 'uiauto/Automation.tracetemplate')
);
// in future all the blackberries go here.
this.active = 'iOS';
if (typeof this.devices[this.active] === 'undefined') {
this.devices[this.active] = ios(this.rest, this.args.app, this.args.UDID, this.args.verbose, this.args.remove);
}
this.device = this.devices[this.active];
var me = this;
me.instruments.launch(function() {
console.log('Instruments launched. Starting poll loop for new commands.');
me.instruments.setDebug(true);
cb(null, me);
}, function(code) {
if (!code || code > 0) {
me.stop();
}
this.device.start(function(err, device) {
cb(err, device);
});
} else {
cb('Session already in progress', null);
}
};
Appium.prototype.proxy = function(cmd, cb) {
this.device.proxy(cmd, cb);
};
Appium.prototype.stop = function(cb) {
if (this.sessionId === null) {
return;
}
var me = this;
console.log('Shutting down appium session ' + me.sessionId);
this.instruments.shutdown(function(traceDir) {
me.queue = [];
me.progress = 0;
this.device.stop(function() {
console.log('Shutting down appium session.');
me.sessionId = null;
rimraf(traceDir, function() {
if (cb) {
cb();
}
});
if (cb) {
cb(me.sessionId);
}
});
};
Appium.prototype.proxy = function(command, cb) {
// was thinking we should use a queue for commands instead of writing to a file
this.push([command, cb]);
console.log('Pushed command to appium work queue: ' + command);
Appium.prototype.device = function() {
return this.devices[this.active];
};
Appium.prototype.push = function(elem) {
this.queue.push(elem);
var me = this;
var next = function() {
if (me.queue.length <= 0 || me.progress > 0) {
return;
}
var target = me.queue.shift();
me.progress++;
me.instruments.sendCommand(target[0], function(result) {
if (typeof target[1] === 'function') {
if (result === 'undefined') {
target[1]();
} else {
try {
var jsonresult = JSON.parse(result);
target[1](jsonresult);
} catch (e) {
target[1](result);
}
}
}
// maybe there's moar work to do
me.progress--;
next();
});
};
next();
};
module.exports = function(app, udid, version) {
return new Appium(app, udid, version);
module.exports = function(args) {
return new Appium(args);
};

Просмотреть файл

@ -8,7 +8,7 @@ var findElement = function(req, res, ctx, many, cb) {
var command = [ctx, ".findElement", ext, "AndSetKey", ext, "('", value, "')"].join("");
req.appium.proxy(command, function(json) {
req.device.proxy(command, function(json) {
json = many ? json : json[0];
cb({
sessionId: req.appium.sessionId
@ -33,7 +33,7 @@ exports.getStatus = function(req, res) {
};
exports.createSession = function(req, res) {
// we can talk to the appium client from here
// we can talk to the device client from here
req.appium.start(function(err, instance) {
if (err) {
// of course we need to deal with err according to the WDJP spec.
@ -83,7 +83,7 @@ exports.executeScript = function(req, res) {
var iosResponse ='';
var requestData = req.body;
try {
iosResponse = appium.client.proxy(requestData.script, true);
iosResponse = device.client.proxy(requestData.script, true);
}
catch (e) {
var errObj = {sessionId: sessionId, 'status': 13, 'value': JSON.stringify(e)};
@ -112,7 +112,7 @@ exports.setValue = function(req, res) {
var command = ["elements['", elementId, "'].setValue('", body, "')"].join('');
req.appium.proxy(command, function(json) {
req.device.proxy(command, function(json) {
res.send({
sessionId: req.appium.sessionId
, status: status
@ -128,7 +128,7 @@ exports.doClick = function(req, res) {
var command = ["elements['", elementId, "'].tap()"].join('');
req.appium.proxy(command, function(json) {
req.device.proxy(command, function(json) {
res.send({
sessionId: req.appium.sessionId
, status: status
@ -144,7 +144,7 @@ exports.getText = function(req, res) {
var command = ["elements['", elementId, "'].getText()"].join('');
req.appium.proxy(command, function(json) {
req.device.proxy(command, function(json) {
res.send({
sessionId: req.appium.sessionId
, status: status

96
app/ios.js Normal file
Просмотреть файл

@ -0,0 +1,96 @@
var path = require('path')
, rimraf = require('rimraf')
, instruments = require('../instruments/instruments');
var IOS = function(rest, app, udid, verbose, removeTraceDir) {
this.rest = rest;
this.app = app;
this.udid = udid;
this.verbose = verbose;
this.instruments = null;
this.queue = [];
this.progress = 0;
this.removeTraceDir = removeTraceDir;
};
IOS.prototype.start = function(cb) {
if (this.instruments === null) {
this.instruments = instruments(
this.rest
, path.resolve(__dirname, '../' + this.app)
, this.udid
, path.resolve(__dirname, 'uiauto/bootstrap.js')
, path.resolve(__dirname, 'uiauto/Automation.tracetemplate')
);
}
var me = this;
me.instruments.launch(function() {
console.log('Instruments launched. Starting poll loop for new commands.');
me.instruments.setDebug(true);
cb(null, me);
}, function(code) {
if (!code || code > 0) {
me.stop();
}
});
};
IOS.prototype.stop = function(cb) {
var me = this;
this.instruments.shutdown(function(traceDir) {
me.queue = [];
me.progress = 0;
rimraf(traceDir, function() {
if (cb) {
cb();
}
});
});
};
IOS.prototype.proxy = function(command, cb) {
// was thinking we should use a queue for commands instead of writing to a file
this.push([command, cb]);
console.log('Pushed command to appium work queue: ' + command);
};
IOS.prototype.push = function(elem) {
this.queue.push(elem);
var me = this;
var next = function() {
if (me.queue.length <= 0 || me.progress > 0) {
return;
}
var target = me.queue.shift();
me.progress++;
me.instruments.sendCommand(target[0], function(result) {
if (typeof target[1] === 'function') {
if (result === 'undefined') {
target[1]();
} else {
try {
var jsonresult = JSON.parse(result);
target[1](jsonresult);
} catch (e) {
target[1](result);
}
}
}
// maybe there's moar work to do
me.progress--;
next();
});
};
next();
};
module.exports = function(rest, app, udid, verbose, removeTraceDir) {
return new IOS(rest, app, udid, verbose, removeTraceDir);
};

Просмотреть файл

@ -4,6 +4,7 @@ module.exports = function(appium) {
var rest = appium.rest
, inject = function(req, res, next) {
req.appium = appium;
req.device = appium.device;
next();
};

Просмотреть файл

@ -9,10 +9,13 @@ var http = require('http')
, appium = require('./app/appium')
, parser = require('./app/parser');
var main = function(app, udid, verbose, port, address, remove, doneCb) {
var main = function(args, doneCb) {
if (typeof doneCb === "undefined") {
doneCb = function() {};
}
// in case we'll support blackberry at some point
args.device = 'iOS';
rest.configure(function() {
var bodyParser = express.bodyParser()
, parserWrap = function(req, res, next) {
@ -31,12 +34,12 @@ var main = function(app, udid, verbose, port, address, remove, doneCb) {
rest.use(rest.router);
});
// Instantiate the appium instance
var appiumServer = appium(app, udid, verbose, remove);
var appiumServer = appium(args);
// Hook up REST http interface
appiumServer.attachTo(rest);
// Start the web server that receives all the commands
server.listen(port, address, function() {
var logMessage = "Appium REST http interface listener started on "+address+":"+port;
server.listen(args.port, args.address, function() {
var logMessage = "Appium REST http interface listener started on "+args.address+":"+args.port;
console.log(logMessage.cyan);
});
server.on('close', doneCb);
@ -45,7 +48,7 @@ var main = function(app, udid, verbose, port, address, remove, doneCb) {
if (require.main === module) {
// Parse the command line arguments
var args = parser().parseArgs();
main(args.app, args.UDID, args.verbose, args.port, args.address, args.remove);
main(args);
}
module.exports.run = main;