standardize ways of generating appium responses to conform to jsonwp

This commit is contained in:
Jonathan Lipps
2013-01-29 12:26:10 -08:00
parent 79239c8700
commit 83f8bf4594
6 changed files with 159 additions and 139 deletions
+70 -30
View File
@@ -1,29 +1,73 @@
// Appium webserver controller methods
// https://github.com/hugs/appium/blob/master/appium/server.py
"use strict";
var status = require('./uiauto/lib/status');
var status = require('./uiauto/lib/status')
, _ = require('underscore');
function getResponseHandler(req, res, validateResponse) {
function getResponseHandler(req, res) {
var responseHandler = function(err, response) {
if (typeof response === "undefined" || response === null) {
response = {};
}
if (req.appium || response.sessionId) {
response.sessionId = req.appium.sessionId || response.sessionId || null;
}
if (err !== null) {
res.send(500, {message: "A server error occurred: " + err});
} else {
if (typeof(validateResponse) === 'function') {
// If a validate method was provided, use it to update the response
response = validateResponse(response);
var value = response.value;
if (typeof value === "undefined") {
value = {};
}
respondError(req, res, err.message, value);
} else {
if (response.status === 0) {
respondSuccess(req, res, response.value);
} else {
respondError(req, res, response.status, response.value);
}
res.send(response);
}
};
return responseHandler;
}
var getSessionId = function(req, response) {
var sessionId = response.sessionId;
if (typeof sessionId === "undefined") {
if (req.appium) {
sessionId = req.appium.sessionId || null;
} else {
sessionId = null;
}
}
if (typeof sessionId !== "string" && sessionId !== null) {
sessionId = null;
}
return sessionId;
};
var respondError = function(req, res, statusObj, value) {
var code, message;
if (typeof statusObj === "string") {
code = 1;
message = statusObj;
} else if (typeof statusObj === "number") {
code = statusObj;
message = status.getSummaryByCode(code);
} else {
code = statusObj.code;
message = statusObj.summary;
}
var newValue = _.extend({message: message}, value);
var response = {status: code, value: newValue};
response.sessionId = getSessionId(req, response);
res.send(500, response);
};
var respondSuccess = function(req, res, value) {
var response = {status: status.codes.Success.code, value: value};
response.sessionId = getSessionId(req, response);
if (typeof response.value === "undefined") {
response.value = '';
}
res.send(response);
};
exports.sessionBeforeFilter = function(req, res, next) {
var match = new RegExp("([^/]+)").exec(req.params[0]);
var sessId = match ? match[1] : null;
@@ -37,11 +81,9 @@ exports.sessionBeforeFilter = function(req, res, next) {
exports.getStatus = function(req, res) {
// Return a static JSON object to the client
getResponseHandler(req, res)(null, {
status: status.codes.Success.code,
value: {
build: {version: 'Appium 1.0'}
}});
respondSuccess(req, res, {
build: {version: 'Appium 1.0'}
});
};
exports.createSession = function(req, res) {
@@ -49,31 +91,29 @@ exports.createSession = function(req, res) {
var desired = req.body.desiredCapabilities;
req.appium.start(req.body.desiredCapabilities, function(err, instance) {
if (err) {
return res.send({status: status.codes.NoSuchDriver, value: err});
}
if (desired && desired.newCommandTimeout) {
instance.setCommandTimeout(desired.newCommandTimeout, function() {
respondError(req, res, status.codes.NoSuchDriver);
} else {
if (desired && desired.newCommandTimeout) {
instance.setCommandTimeout(desired.newCommandTimeout, function() {
res.set('Location', "/wd/hub/session/" + req.appium.sessionId);
res.send(303);
});
} else {
res.set('Location', "/wd/hub/session/" + req.appium.sessionId);
res.send(303);
});
} else {
res.set('Location', "/wd/hub/session/" + req.appium.sessionId);
res.send(303);
}
}
});
};
exports.getSession = function(req, res) {
// Return a static JSON object to the client
getResponseHandler(req, res)(null, {
status: status.codes.Success.code,
value: req.device.capabilities
});
respondSuccess(req, res, req.device.capabilities);
};
exports.getSessions = function(req, res) {
res.send([{id: req.appium.sessionId , capabilities: req.device.capabilities}]);
respondSuccess(req, res,
[{id: req.appium.sessionId , capabilities: req.device.capabilities}]);
};
exports.deleteSession = function(req, res) {
+71 -106
View File
@@ -121,6 +121,26 @@ IOS.prototype.proxy = function(command, cb) {
logger.info('Pushed command to appium work queue: ' + command);
};
IOS.prototype.respond = function(response, cb) {
if (typeof response === 'undefined') {
cb(null, '');
} else {
if (typeof(response) !== "object") {
cb(new UnknownError(), response);
} else if (!('status' in response)) {
cb(new ProtocolError('Status missing in response from device'), response);
} else {
var status = parseInt(response.status, 10);
if (isNaN(status)) {
cb(new ProtocolError('Invalid status in response from device'), response);
} else {
response.status = status;
cb(null, response);
}
}
}
};
IOS.prototype.push = function(elem) {
this.queue.push(elem);
var me = this;
@@ -141,23 +161,7 @@ IOS.prototype.push = function(elem) {
me.instruments.sendCommand(command, function(response) {
me.cbForCurrentCmd = null;
if (typeof cb === 'function') {
if (typeof response === 'undefined') {
cb(null, null);
} else {
if (typeof(response) !== "object") {
cb(new UnknownError(), response);
} else if (!('status' in response)) {
cb(new ProtocolError('Status missing in response from device'), response);
} else {
var status = parseInt(response.status, 10);
if (isNaN(status)) {
cb(new ProtocolError('Invalid status in response from device'), response);
} else {
response.status = status;
cb(null, response);
}
}
}
me.respond(response, cb);
}
// maybe there's moar work to do
@@ -206,138 +210,102 @@ IOS.prototype.findElementsFromElement = function(element, strategy, selector, cb
IOS.prototype.setValue = function(elementId, value, cb) {
var command = ["au.getElement('", elementId, "').setValue('", value, "')"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.click = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').tap()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.clear = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').setValue('')"].join('');
this.proxy(command, function(err, json) {
cb(null, json);
});
this.proxy(command, cb);
};
IOS.prototype.getText = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').value()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.getAttribute = function(elementId, attributeName, cb) {
var command = ["au.getElement('", elementId, "').", attributeName, "()"].join('');
this.proxy(command, function(err, json) {
cb(null, json);
});
this.proxy(command, cb);
};
IOS.prototype.getLocation = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').getElementLocation()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.getSize = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').getElementSize()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.keys = function(elementId, keys, cb) {
var command = ["sendKeysToActiveElement('", keys ,"')"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.frame = function(frame, cb) {
frame = frame? frame : 'mainWindow';
var command = ["wd_frame = ", frame].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.implicitWait = function(seconds, cb) {
var command = ["au.timeout('", seconds, "')"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.elementDisplayed = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').isDisplayed()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.elementEnabled = function(elementId, cb) {
var command = ["au.getElement('", elementId, "').isEnabled()"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.getPageSource = function(cb) {
this.proxy("wd_frame.getPageSource()", function(err, json) {
cb(err, json);
});
this.proxy("wd_frame.getPageSource()", cb);
};
IOS.prototype.getAlertText = function(cb) {
this.proxy("getAlertText()", function(err, json) {
cb(err, json);
});
this.proxy("getAlertText()", cb);
};
IOS.prototype.postAcceptAlert = function(cb) {
this.proxy("acceptAlert()", function(err, json) {
cb(err, json);
});
this.proxy("acceptAlert()", cb);
};
IOS.prototype.postDismissAlert = function(cb) {
this.proxy("dismissAlert()", function(err, json) {
cb(err, json);
});
this.proxy("dismissAlert()", cb);
};
IOS.prototype.getOrientation = function(cb) {
var command = "getScreenOrientation()";
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.setOrientation = function(orientation, cb) {
var command = ["setScreenOrientation('", orientation ,"')"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.getScreenshot = function(cb) {
@@ -346,34 +314,37 @@ IOS.prototype.getScreenshot = function(cb) {
var shotPath = ["/tmp/", this.instruments.guid, "/Run 1/screenshot", guid, ".png"].join("");
this.proxy(command, function(err, response) {
var delayTimes = 0;
var onErr = function() {
delayTimes++;
delay(0.2);
if (delayTimes <= 10) {
read(onErr);
} else {
read();
}
};
var read = function(onErr) {
fs.readFile(shotPath, function read(err, data) {
if (err) {
if (onErr) {
onErr();
} else {
response.value = '';
response.status = status.codes.UnknownError.code;
cb(err, null);
}
if (err) {
cb(err, response);
} else {
var delayTimes = 0;
var onErr = function() {
delayTimes++;
delay(0.2);
if (delayTimes <= 10) {
read(onErr);
} else {
var b64data = new Buffer(data).toString('base64');
response.value = b64data;
cb(null, response);
read();
}
});
};
read(onErr);
};
var read = function(onErr) {
fs.readFile(shotPath, function read(err, data) {
if (err) {
if (onErr) {
onErr();
} else {
response.value = '';
response.status = status.codes.UnknownError.code;
}
} else {
var b64data = new Buffer(data).toString('base64');
response.value = b64data;
}
cb(err, response);
});
};
read(onErr);
}
});
};
@@ -386,17 +357,13 @@ IOS.prototype.flick = function(xSpeed, ySpeed, swipe, cb) {
command = ["touchFlickFromSpeed(", xSpeed, ",", ySpeed,")"].join('');
}
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.flickElement = function(elementId, xoffset, yoffset, speed, cb) {
var command = ["au.getElement('", elementId, "').touchFlick(", xoffset, ",", yoffset, ",", speed, ")"].join('');
this.proxy(command, function(err, json) {
cb(err, json);
});
this.proxy(command, cb);
};
IOS.prototype.url = function(cb) {
@@ -406,9 +373,7 @@ IOS.prototype.url = function(cb) {
};
IOS.prototype.active = function(cb) {
this.proxy("au.getActiveElement()", function(err, json) {
cb(null, json);
});
this.proxy("au.getActiveElement()", cb);
};
module.exports = function(rest, app, udid, verbose, removeTraceDir) {
+1 -1
View File
@@ -23,7 +23,7 @@ while(true) {
console.log("Got new command from instruments: " + cmd);
var result = eval(cmd);
if (typeof result === "undefined") {
result = {value: false};
result = '';
console.log("Command executed without response");
}
if (typeof result.status === "undefined") {
+11
View File
@@ -1,3 +1,5 @@
"use strict";
var codes = {
Success: {
code: 0,
@@ -103,4 +105,13 @@ var codes = {
if (typeof module !== "undefined") {
module.exports.codes = codes;
module.exports.getSummaryByCode = function(code) {
code = parseInt(code, 10);
for (var c in codes) {
if (typeof codes[c].code !== "undefined" && codes[c].code == code) {
return codes[c].summary;
}
}
return 'An error occurred';
};
}
+5 -1
View File
@@ -26,11 +26,14 @@ var main = function(args, readyCb, doneCb) {
rest.use(express.methodOverride());
rest.use(rest.router);
});
// Instantiate the appium instance
var appiumServer = appium(args);
// Hook up REST http interface
appiumServer.attachTo(rest);
// Start the web server that receives all the commands
// Start the server either now or after pre-launching device
var next = function(appiumServer) {
server.listen(args.port, args.address, function() {
var logMessage = "Appium REST http interface listener started on "+args.address+":"+args.port;
@@ -46,6 +49,7 @@ var main = function(args, readyCb, doneCb) {
} else {
next(appiumServer);
}
server.on('close', doneCb);
return server;
};
+1 -1
View File
@@ -14,7 +14,7 @@ describeWd('check getSessions', function(h) {
, method: "GET"
, json: true
}, function(err, response, body) {
assert.equal(h.sessionId, body[0].id);
assert.equal(h.sessionId, body.value[0].id);
done();
});
});