Browse files

[api fix test] A couple of fixes for liberal arguments parsing, as we…

…ll as edge-cases in the .wait() method. Added `options.stream` for expecting from process.stderr
  • Loading branch information...
1 parent 14ef865 commit df5c64deedc2376ca8f8000b067deea807ca4213 @indexzero indexzero committed Aug 10, 2011
Showing with 91 additions and 31 deletions.
  1. +69 −19 lib/nexpect.js
  2. +22 −12 test/nexpect-test.js
View
88 lib/nexpect.js
@@ -22,6 +22,10 @@ function chain (context) {
sendline: function (line) {
var _sendline = function _sendline () {
context.process.stdin.write(line + '\n');
+
+ if (context.verbose) {
+ process.stdout.write(line + '\n');
+ }
};
_sendline.shift = true;
@@ -59,6 +63,26 @@ function chain (context) {
callback(err);
}
+ function validateFnType (currentFn) {
+ if (typeof currentFn !== 'function') {
+ //
+ // If the `currentFn` is not a function, short-circuit with an error.
+ //
+ onError(new Error('Cannot process non-function on nexpect stack.'), true);
+ return false;
+ }
+ else if (['_expect', '_sendline', '_wait'].indexOf(currentFn.name) === -1) {
+ //
+ // If the `currentFn` is a function, but not those set by `.sendline()` or
+ // `.expect()` then short-circuit with an error.
+ //
+ onError(new Error('Unexpected context function name: ' + currentFn.name), true);
+ return false;
+ }
+
+ return true;
+ }
+
function evalContext (data, name) {
var currentFn = context.queue[0];
@@ -74,18 +98,8 @@ function chain (context) {
context.queue.shift();
}
- if (typeof currentFn !== 'function') {
- //
- // If the `currentFn` is not a function, short-circuit with an error.
- //
- return onError(new Error('Cannot process non-function on nexpect stack.'), true);
- }
- else if (['_expect', '_sendline', '_wait'].indexOf(currentFn.name) === -1) {
- //
- // If the `currentFn` is a function, but not those set by `.sendline()` or
- // `.expect()` then short-circuit with an error.
- //
- return onError(new Error('Unexpected context function name: ' + currentFn.name), true);
+ if (!validateFnType(currentFn)) {
+ return;
}
if (currentFn.name === '_expect') {
@@ -130,20 +144,56 @@ function chain (context) {
if (context.ignoreCase) {
data = data.toLowerCase();
}
-
- stdout = stdout.concat(data.split('\n').filter(function (line) { line !== '' }));
- evalContext(data, null);
- };
+
+ var lines = data.split('\n').filter(function (line) { return line.length > 0 });
+ stdout = stdout.concat(lines);
+
+ while (lines.length > 0) {
+ evalContext(lines.shift(), null);
+ }
+ }
+
+ function flushQueue () {
+ var currentFn = context.queue.shift(),
+ lastLine = stdout[stdout.length - 1];
+
+ if (!lastLine) {
+ onError(new Error('No data from child with non-empty queue.'))
+ return false;
+ }
+ else if (context.queue.length > 0) {
+ onError(new Error('Non-empty queue on spawn exit.'));
+ return false;
+ }
+ else if (!validateFnType(currentFn)) {
+ return false;
+ }
+ else if (currentFn.name === '_sendline') {
+ onError(new Error('Cannot call sendline after the process has exited'));
+ return false;
+ }
+ else if (currentFn.name === '_wait' || currentFn.name === '_expect') {
+ if (currentFn(lastLine) !== true) {
+ onError(new Error(lastLine + ' was not expected..'));
+ return false
+ }
+ }
+
+ return true;
+ }
context.process = spawn(context.command, context.params);
- context.process.stdout.on('data', onLine);
+ context.process[context.stream].on('data', onLine);
context.process.on('exit', function (code, signal) {
if (code === 127) {
//
// If the response code is `127` then `context.command` was not found.
//
return onError(new Error('Command not found: ' + context.command));
}
+ else if (context.queue.length && !flushQueue()) {
+ return;
+ }
callback(null, stdout);
});
@@ -156,12 +206,11 @@ function chain (context) {
function nspawn (command, params, options) {
if (arguments.length === 2) {
if (Array.isArray(arguments[1])) {
- params = arguments[1];
options = {};
}
else {
- params = [];
options = arguments[1];
+ params = null;
}
}
@@ -180,6 +229,7 @@ function nspawn (command, params, options) {
command: command,
params: params,
queue: [],
+ stream: options.stream || 'stdout',
verbose: options.verbose,
stripColors: options.stripColors,
ignoreCase: options.ignoreCase
View
34 test/nexpect-test.js
@@ -30,7 +30,6 @@ function assertError (expect) {
},
"should respond with no error": function (_, err) {
assert.isObject(err);
- assert.isNotNull(err.message.match(/^Command not found/));
}
}
}
@@ -47,8 +46,8 @@ vows.describe('nexpect').addBatch({
nexpect.spawn("echo", ["hello"])
.expect("hello")
),
- "`ls -al /tmp/undefined`": assertSpawn(
- nexpect.spawn("ls -la /tmp/undefined")
+ "`ls -l /tmp/undefined`": assertSpawn(
+ nexpect.spawn("ls -la /tmp/undefined", { stream: 'stderr' })
.expect("No such file or directory")
),
"a command that does not exist": assertError(
@@ -62,15 +61,26 @@ vows.describe('nexpect').addBatch({
.expect("testing")
.sendline("process.exit()")
),
- "and using the wait() method": assertSpawn(
- nexpect.spawn(path.join(__dirname, 'fixtures', 'prompt-and-respond'))
- .wait('first')
- .sendline('first-prompt')
- .expect('first-prompt')
- .wait('second')
- .sendline('second-prompt')
- .expect('second-prompt')
- ),
+ "and using the wait() method": {
+ "when assertions are met": assertSpawn(
+ nexpect.spawn(path.join(__dirname, 'fixtures', 'prompt-and-respond'))
+ .wait('first')
+ .sendline('first-prompt')
+ .expect('first-prompt')
+ .wait('second')
+ .sendline('second-prompt')
+ .expect('second-prompt')
+ ),
+ "when the last assertion is never met": assertError(
+ nexpect.spawn(path.join(__dirname, 'fixtures', 'prompt-and-respond'))
+ .wait('first')
+ .sendline('first-prompt')
+ .expect('first-prompt')
+ .wait('second')
+ .sendline('second-prompt')
+ .wait('this-never-shows-up')
+ )
+ },
"when options.stripColors is set": assertSpawn(
nexpect.spawn(path.join(__dirname, 'fixtures', 'log-colors'), { stripColors: true })
.wait('second has colors')

0 comments on commit df5c64d

Please sign in to comment.