protractor
Version:
Webdriver E2E test wrapper for Angular.
151 lines (133 loc) • 4.79 kB
JavaScript
var child_process = require('child_process'),
q = require('q'),
net = require('net');
var TIMEOUT = 10000;
// An instance of a protractor debugger server.
var Server = function(serverStartCmd, port) {
// Start protractor and its debugger server as a child process.
this.start = function() {
var deferred = q.defer();
var received = '';
serverStartCmd += ' --debuggerServerPort ' + port;
serverStartCmd = serverStartCmd.split(/\s/);
var test_process = child_process.spawn(serverStartCmd[0],
serverStartCmd.slice(1));
var timeoutObj = setTimeout(function() {
var errMsg = 'Did not start interactive server in ' + TIMEOUT/1000 + 's.';
if (received) {
errMsg += ' Server startup output: ' + received;
}
deferred.reject(errMsg);
}, TIMEOUT);
test_process.stdout.on('data', function(data) {
received += data;
if (received.indexOf('Server listening on 127.0.0.1:' + port) >= 0) {
clearTimeout(timeoutObj);
// Add a small time for browser to get ready
setTimeout(deferred.resolve, 2000);
}
});
test_process.stderr.on('data', function(data) {
received += data;
});
return deferred.promise;
};
};
// A client to attach to Protractor's debugger server and exchange data.
var Client = function(port) {
var socket;
// Connect to the server.
this.connect = function() {
var deferred = q.defer();
socket = net.connect({port: port}, function() {
deferred.resolve();
});
return deferred.promise;
};
// Disconnect from the server.
this.disconnect = function() {
socket.end();
};
// Send a command to the server and wait for a response. Return response as a
// promise.
this.sendCommand = function(cmd) {
var deferred = q.defer();
var received = '';
var timeoutObj = setTimeout(function() {
var errMsg = 'Command <' + JSON.stringify(cmd) +
'> did not receive a response in ' + TIMEOUT/1000 + 's.';
if (received) {
errMsg += ' Received messages so far: ' + received;
}
deferred.reject(errMsg);
}, TIMEOUT);
var ondata = function(data) {
received += data.toString();
var i = received.indexOf('\r\n');
if (i >= 0) {
clearTimeout(timeoutObj);
var response = received.substring(0, i).trim();
deferred.resolve(response);
}
};
socket.on('data', ondata);
var onerror = function(data) {
deferred.reject('Received error: ' + data);
};
socket.on('error', onerror);
socket.write(cmd + '\r\n');
return deferred.promise.fin(function() {
clearTimeout(timeoutObj);
socket.removeListener('data', ondata);
socket.removeListener('error', onerror);
});
};
};
/**
* Util for running an interactive Protractor test.
*/
exports.InteractiveTest = function(interactiveServerStartCmd, port) {
var expectations = [];
// Adds a command to send as well as the response to verify against.
// If opt_expectedResult is undefined, the test will still wait for the server
// to respond after sending the command, but will not verify against it.
// Note, this does not actually interact with the server, but simply adds the
// command to a queue.
this.addCommandExpectation = function(command, opt_expectedResult) {
expectations.push({
command: command,
expectedResult: opt_expectedResult
});
};
// Execute the interactive test. This will first start Protractor and its
// debugger server. Then it will connect to the server. Finally, it will
// send the queue of commands against the server sequentially and verify the
// response from the server if needed.
this.run = function() {
var server = new Server(interactiveServerStartCmd, port);
return server.start().then(function() {
var client = new Client(port);
return client.connect().then(function() {
var verifyAll = function(i) {
if (i < expectations.length) {
var expectedResult = expectations[i].expectedResult;
var command = expectations[i].command;
return client.sendCommand(command).then(function(response) {
if (expectedResult !== undefined && expectedResult !== response) {
throw ('Command <' + JSON.stringify(command) + '> received: ' +
response + ', but expects: ' + expectedResult);
} else {
return verifyAll(i + 1);
}
});
}
};
return verifyAll(0);
}).fin(function() {
// '^]' This is the term signal.
client.sendCommand(String.fromCharCode(0x1D));
client.disconnect();
});
}).done();
};
};