exports.testPathological = function() { var args; var requ = new Requisition(); args = requ._tokenize('a\\ b \\t\\n\\r \\\'x\\\" \'d'); // a_b \t\n\r \'x\" 'd test.is(4, args.length); test.is('a b', args[0].text); test.is('', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof Argument); test.is('\t\n\r', args[1].text); test.is(' ', args[1].prefix); test.is('', args[1].suffix); test.ok(args[1] instanceof Argument); test.is('\'x"', args[2].text); test.is(' ', args[2].prefix); test.is('', args[2].suffix); test.ok(args[2] instanceof Argument); test.is('d', args[3].text); test.is(' \'', args[3].prefix); test.is('', args[3].suffix); test.ok(args[3] instanceof Argument); };
exports.testRegularNesting = function() { var args; var requ = new Requisition(); args = requ._tokenize('{"x"}'); test.is(1, args.length); test.is('"x"', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{\'x\'}'); test.is(1, args.length); test.is('\'x\'', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('"{x}"'); test.is(1, args.length); test.is('{x}', args[0].text); test.is('"', args[0].prefix); test.is('"', args[0].suffix); test.ok(args[0] instanceof Argument); args = requ._tokenize('\'{x}\''); test.is(1, args.length); test.is('{x}', args[0].text); test.is('\'', args[0].prefix); test.is('\'', args[0].suffix); test.ok(args[0] instanceof Argument); };
var doTest = function(match, against) { // Only log the real textContent if the test fails if (against.match(match) != null) { assert.ok(true, 'html output for \'' + name + '\' ' + 'should match /' + match.source || match + '/'); } else { assert.ok(false, 'html output for \'' + name + '\' ' + 'should match /' + match.source || match + '/. ' + 'Actual textContent: "' + against + '"'); } };
exports.testIncompleteMultiMatch = function() { update({ typed: 't', cursor: { start: 1, end: 1 } }); test.is( 'I', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.ok(assignC.getPredictions().length > 0); test.ok(assignC.getPredictions().length < 20); // could break ... verifyPredictionsContains('tsv', assignC.getPredictions()); verifyPredictionsContains('tsr', assignC.getPredictions()); test.is(null, requ.commandAssignment.getValue()); };
helpers.arrayIs = function(actual, expected, message) { assert.ok(Array.isArray(actual), 'actual is not an array: ' + message); assert.ok(Array.isArray(expected), 'expected is not an array: ' + message); if (!Array.isArray(actual) || !Array.isArray(expected)) { return; } assert.is(actual.length, expected.length, 'array length: ' + message); for (var i = 0; i < actual.length && i < expected.length; i++) { assert.is(actual[i], expected[i], 'member[' + i + ']: ' + message); } };
var doTest = function(match, against) { if (!match.test(against)) { assert.ok(false, "html output for " + typed + " against " + match.source); console.log("Actual textContent"); console.log(against); } };
var checkOutput = assert.checkCalled(function() { var div = helpers._options.window.document.createElement('div'); output.toDom(div); var displayed = div.textContent.trim(); if (tests.outputMatch) { var doTest = function(match, against) { if (!match.test(against)) { assert.ok(false, "html output for " + typed + " against " + match.source); console.log("Actual textContent"); console.log(against); } }; if (Array.isArray(tests.outputMatch)) { tests.outputMatch.forEach(function(match) { doTest(match, displayed); }); } else { doTest(tests.outputMatch, displayed); } } if (tests.blankOutput != null) { if (!/^$/.test(displayed)) { assert.ok(false, "html for " + typed + " (textContent sent to info)"); console.log("Actual textContent"); console.log(displayed); } } }, this);
exports.testStrangeNesting = function() { var args; var requ = new Requisition(); // Note: When we get real JS parsing this should break args = requ._tokenize('{"x}"}'); test.is(2, args.length); test.is('"x', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); test.is('}', args[1].text); test.is('"', args[1].prefix); test.is('', args[1].suffix); test.ok(args[1] instanceof Argument); };
return inputter.handleKeyUp(ev1).then(function() { assert.ok(latestEvent != null, 'events this test'); assert.is(latestData, 'Exec: tss ', 'last command is tss'); assert.is(inputter.element.value, '', 'inputter should exec on RETURN keyUp'); assert.ok(focusManager._recentOutput, 'recent output happened'); var ev2 = { keyCode: KeyEvent.DOM_VK_F1 }; return inputter.handleKeyUp(ev2).then(function() { assert.ok(!focusManager._recentOutput, 'no recent output happened post F1'); assert.ok(focusManager._helpRequested, 'F1 = help'); var ev3 = { keyCode: KeyEvent.DOM_VK_ESCAPE }; return inputter.handleKeyUp(ev3).then(function() { assert.ok(!focusManager._helpRequested, 'ESCAPE = anti help'); }); }); });
exports.testPredictions = function(options) { if (options.window.isFake || options.isFirefox) { test.log('Skipping resource tests: window.isFake || isFirefox'); return; } var resource1 = types.getType('resource'); var options1 = resource1.getLookup(); test.ok(options1.length > 1, 'have resources'); options1.forEach(function(prediction) { checkPrediction(resource1, prediction); }); var resource2 = types.getType({ name: 'resource', include: 'text/javascript' }); var options2 = resource2.getLookup(); test.ok(options2.length > 1, 'have resources'); options2.forEach(function(prediction) { checkPrediction(resource2, prediction); }); var resource3 = types.getType({ name: 'resource', include: 'text/css' }); var options3 = resource3.getLookup(); // jsdom fails to support digging into stylesheets if (!options.isNode) { test.ok(options3.length >= 1, 'have resources'); } else { test.log('Running under Node. ' + 'Skipping checks due to jsdom document.stylsheets support.'); } options3.forEach(function(prediction) { checkPrediction(resource3, prediction); }); var resource4 = types.getType({ name: 'resource' }); var options4 = resource4.getLookup(); test.is(options1.length, options4.length, 'type spec'); test.is(options2.length + options3.length, options4.length, 'split'); };
Object.keys(checks.args).forEach(function(paramName) { var check = checks.args[paramName]; var assignment; if (paramName === 'command') { assignment = requisition.commandAssignment; } else { assignment = requisition.getAssignment(paramName); } if (assignment == null) { assert.ok(false, 'Unknown arg: ' + paramName); return; } if ('value' in check) { assert.is(assignment.value, check.value, 'arg.' + paramName + '.value'); } if ('name' in check) { assert.is(assignment.value.name, check.name, 'arg.' + paramName + '.name'); } if ('type' in check) { assert.is(assignment.arg.type, check.type, 'arg.' + paramName + '.type'); } if ('arg' in check) { assert.is(assignment.arg.toString(), check.arg, 'arg.' + paramName + '.arg'); } if ('status' in check) { assert.is(assignment.getStatus().toString(), check.status, 'arg.' + paramName + '.status'); } if ('message' in check) { assert.is(assignment.getMessage(), check.message, 'arg.' + paramName + '.message'); } });
Object.keys(checks.args).forEach(function(paramName) { var check = checks.args[paramName]; var assignment; if (paramName === 'command') { assignment = requisition.commandAssignment; } else { assignment = requisition.getAssignment(paramName); } if (assignment == null) { test.ok(false, 'Unknown parameter: ' + paramName); return; } if (check.value) { test.is(assignment.value, check.value, 'checkStatus value for ' + paramName); } if (check.name) { test.is(assignment.value.name, check.name, 'checkStatus name for ' + paramName); } if (check.type) { test.is(assignment.arg.type, check.type, 'checkStatus type for ' + paramName); } if (check.arg) { test.is(assignment.arg.toString(), check.arg, 'checkStatus arg for ' + paramName); } if (check.status) { test.is(assignment.getStatus().toString(), check.status, 'checkStatus status for ' + paramName); } if (check.message) { test.is(assignment.getMessage(), check.message, 'checkStatus message for ' + paramName); } });
exports.testSimple = function() { var args; var requ = new Requisition(); args = requ._tokenize('s'); test.is(1, args.length); test.is('s', args[0].text); test.is('', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof Argument); args = requ._tokenize('s s'); test.is(2, args.length); test.is('s', args[0].text); test.is('', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof Argument); test.is('s', args[1].text); test.is(' ', args[1].prefix); test.is('', args[1].suffix); test.ok(args[1] instanceof Argument); };
exports.testBasic = function() { input('{'); check('V', Status.ERROR, ''); input('{ '); check('VV', Status.ERROR, ''); input('{ w'); check('VVI', Status.ERROR, 'w', 'window'); input('{ windo'); check('VVIIIII', Status.ERROR, 'windo', 'window'); input('{ window'); check('VVVVVVVV', Status.VALID, 'window', 0); input('{ window.d'); check('VVIIIIIIII', Status.ERROR, 'window.d', 'window.document'); input('{ window.document.title'); check('VVVVVVVVVVVVVVVVVVVVVVV', Status.VALID, 'window.document.title', 0); input('{ d'); check('VVI', Status.ERROR, 'd', 'document'); input('{ document.title'); check('VVVVVVVVVVVVVVVV', Status.VALID, 'document.title', 0); test.ok('donteval' in globalObject, 'donteval exists'); input('{ don'); check('VVIII', Status.ERROR, 'don', 'donteval'); input('{ donteval'); check('VVVVVVVVVV', Status.VALID, 'donteval', 0); /* // This is a controversial test - technically we can tell that it's an error // because 'donteval.' is a syntax error, however donteval is unsafe so we // are playing safe by bailing out early. It's enough of a corner case that // I don't think it warrants fixing input('{ donteval.'); check('VVIIIIIIIII', Status.ERROR, 'donteval.', 0); */ input('{ donteval.cant'); check('VVVVVVVVVVVVVVV', Status.VALID, 'donteval.cant', 0); input('{ donteval.xxx'); check('VVVVVVVVVVVVVV', Status.VALID, 'donteval.xxx', 0); };
exports.testComplex = function() { var args; var requ = new Requisition(); args = requ._tokenize(' 1234 \'12 34\''); test.is(2, args.length); test.is('1234', args[0].text); test.is(' ', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof Argument); test.is('12 34', args[1].text); test.is(' \'', args[1].prefix); test.is('\'', args[1].suffix); test.ok(args[1] instanceof Argument); args = requ._tokenize('12\'34 "12 34" \\'); // 12'34 "12 34" \ test.is(3, args.length); test.is('12\'34', args[0].text); test.is('', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof Argument); test.is('12 34', args[1].text); test.is(' "', args[1].prefix); test.is('"', args[1].suffix); test.ok(args[1] instanceof Argument); test.is('\\', args[2].text); test.is(' ', args[2].prefix); test.is('', args[2].suffix); test.ok(args[2] instanceof Argument); };
forEachType({}, function(type) { var blank = type.getBlank().value; // boolean and array types are exempt from needing undefined blank values if (type.name === 'boolean') { test.is(blank, false, 'blank boolean is false'); } else if (type.name === 'array') { test.ok(Array.isArray(blank), 'blank array is array'); test.is(blank.length, 0, 'blank array is empty'); } else { test.is(blank, undefined, 'default defined for ' + type.name); } });
Object.keys(output.args).forEach(function(arg) { var expectedArg = tests.args[arg]; var actualArg = output.args[arg]; if (Array.isArray(expectedArg)) { if (!Array.isArray(actualArg)) { test.ok(false, 'actual is not an array. ' + typed + '/' + arg); return; } test.is(expectedArg.length, actualArg.length, 'array length: ' + typed + '/' + arg); for (var i = 0; i < expectedArg.length; i++) { test.is(expectedArg[i], actualArg[i], 'member: "' + typed + '/' + arg + '/' + i); } } else { test.is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg); } });
exports.testDeepNesting = function() { var args; var requ = new Requisition(); args = requ._tokenize('{{}}'); test.is(1, args.length); test.is('{}', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{{x} {y}}'); test.is(1, args.length); test.is('{x} {y}', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{{w} {{{x}}}} {y} {{{z}}}'); test.is(3, args.length); test.is('{w} {{{x}}}', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); test.is('y', args[1].text); test.is(' {', args[1].prefix); test.is('}', args[1].suffix); test.ok(args[1] instanceof ScriptArgument); test.is('{{z}}', args[2].text); test.is(' {', args[2].prefix); test.is('}', args[2].suffix); test.ok(args[2] instanceof ScriptArgument); args = requ._tokenize('{{w} {{{x}}} {y} {{{z}}}'); test.is(1, args.length); test.is('{w} {{{x}}} {y} {{{z}}}', args[0].text); test.is('{', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); };
Test.prototype.run = function(options) { assert.currentTest = this; this.status = stati.executing; this.failures = []; this.checks = 0; try { this.func.apply(this.suite, [ options ]); } catch (ex) { assert.ok(false, '' + ex); console.error(ex); if ((options.isNode || options.isFirefox) && ex.stack) { console.error(ex.stack); } } if (this.status === stati.executing) { this.status = stati.pass; } assert.currentTest = null; };
function check(expStatuses, expStatus, expAssign, expPredict) { test.is('{', requ.commandAssignment.value.name, 'is exec'); test.is(expStatuses, statuses, 'unexpected status markup'); test.is(expStatus.toString(), status.toString(), 'unexpected status'); test.is(expAssign, assign.value, 'unexpected assignment'); if (expPredict != null) { var contains; if (Array.isArray(expPredict)) { expPredict.forEach(function(p) { contains = predictionsHas(p); test.ok(contains, 'missing prediction ' + p); }); } else if (typeof expPredict === 'number') { contains = true; test.is(assign.getPredictions().length, expPredict, 'prediction count'); if (assign.getPredictions().length !== expPredict) { assign.getPredictions().forEach(function(prediction) { test.log('actual prediction: ', prediction); }); } } else { contains = predictionsHas(expPredict); test.ok(contains, 'missing prediction ' + expPredict); } if (!contains) { test.log('Predictions: ' + assign.getPredictions().map(function(p) { return p.name; }).join(', ')); } } }
get: function() { test.ok(false, 'donteval should not be used'); return { cant: '', touch: '', 'this': '' }; },
exports.status = function(options, checks) { var requisition = options.display.requisition; var inputter = options.display.inputter; var completer = options.display.completer; if (checks.typed) { inputter.setInput(checks.typed); } else { test.ok(false, "Missing typed for " + JSON.stringify(checks)); return; } if (checks.cursor) { inputter.setCursor(checks.cursor); } if (checks.status) { test.is(requisition.getStatus().toString(), checks.status, "status for " + checks.typed); } var data = completer._getCompleterTemplateData(); if (checks.emptyParameters != null) { var realParams = data.emptyParameters; test.is(realParams.length, checks.emptyParameters.length, 'emptyParameters.length for \'' + checks.typed + '\''); if (realParams.length === checks.emptyParameters.length) { for (var i = 0; i < realParams.length; i++) { test.is(realParams[i].replace(/\u00a0/g, ' '), checks.emptyParameters[i], 'emptyParameters[' + i + '] for \'' + checks.typed + '\''); } } } if (checks.markup) { var cursor = checks.cursor ? checks.cursor.start : checks.typed.length; var statusMarkup = requisition.getInputStatusMarkup(cursor); var actualMarkup = statusMarkup.map(function(s) { return Array(s.string.length + 1).join(s.status.toString()[0]); }).join(''); test.is(checks.markup, actualMarkup, 'markup for ' + checks.typed); } if (checks.directTabText) { test.is(data.directTabText, checks.directTabText, 'directTabText for \'' + checks.typed + '\''); } if (checks.arrowTabText) { test.is(' \u00a0\u21E5 ' + checks.arrowTabText, data.arrowTabText, 'arrowTabText for \'' + checks.typed + '\''); } };
checks.predictionsContains.forEach(function(prediction) { var index = actualPredictions.indexOf(prediction); assert.ok(index !== -1, 'predictionsContains:' + prediction + suffix); });
Object.keys(checks.args).forEach(function(paramName) { var check = checks.args[paramName]; // We allow an 'argument' called 'command' to be the command itself, but // what if the command has a parameter called 'command' (for example, an // 'exec' command)? We default to using the parameter because checking // the command value is less useful var assignment = requisition.getAssignment(paramName); if (assignment == null && paramName === 'command') { assignment = requisition.commandAssignment; } if (assignment == null) { assert.ok(false, 'Unknown arg: ' + paramName + suffix); return; } if ('value' in check) { if (typeof check.value === 'function') { try { check.value(assignment.value); } catch (ex) { assert.ok(false, '' + ex); } } else { assert.is(assignment.value, check.value, 'arg.' + paramName + '.value' + suffix); } } if ('name' in check) { if (options.isJsdom) { assert.log('Skipped arg.' + paramName + '.name due to jsdom'); } else { assert.is(assignment.value.name, check.name, 'arg.' + paramName + '.name' + suffix); } } if ('type' in check) { assert.is(assignment.arg.type, check.type, 'arg.' + paramName + '.type' + suffix); } if ('arg' in check) { assert.is(assignment.arg.toString(), check.arg, 'arg.' + paramName + '.arg' + suffix); } if ('status' in check) { assert.is(assignment.getStatus().toString(), check.status, 'arg.' + paramName + '.status' + suffix); } if ('message' in check) { if (typeof check.message.test === 'function') { assert.ok(check.message.test(assignment.message), 'arg.' + paramName + '.message' + suffix); } else { assert.is(assignment.message, check.message, 'arg.' + paramName + '.message' + suffix); } } });
exports.testJavascript = function() { var args; var requ = new Requisition(); args = requ._tokenize('{x}'); test.is(1, args.length); test.is('x', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{ x }'); test.is(1, args.length); test.is('x', args[0].text); test.is('{ ', args[0].prefix); test.is(' }', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{x} {y}'); test.is(2, args.length); test.is('x', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); test.is('y', args[1].text); test.is(' {', args[1].prefix); test.is('}', args[1].suffix); test.ok(args[1] instanceof ScriptArgument); args = requ._tokenize('{x}{y}'); test.is(2, args.length); test.is('x', args[0].text); test.is('{', args[0].prefix); test.is('}', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); test.is('y', args[1].text); test.is('{', args[1].prefix); test.is('}', args[1].suffix); test.ok(args[1] instanceof ScriptArgument); args = requ._tokenize('{'); test.is(1, args.length); test.is('', args[0].text); test.is('{', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{ '); test.is(1, args.length); test.is('', args[0].text); test.is('{ ', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); args = requ._tokenize('{x'); test.is(1, args.length); test.is('x', args[0].text); test.is('{', args[0].prefix); test.is('', args[0].suffix); test.ok(args[0] instanceof ScriptArgument); };
return requisition.exec({ hidden: true }).then(function(output) { if ('completed' in expected) { assert.is(completed, expected.completed, 'output.completed for: ' + name); } if ('type' in expected) { assert.is(output.type, expected.type, 'output.type for: ' + name); } if ('error' in expected) { assert.is(output.error, expected.error, 'output.error for: ' + name); } if (!options.window) { assert.ok(false, 'Missing options.window in \'' + name + '\'. ' + 'Are you assming that helpers.audit is synchronous? ' + 'It returns a promise'); return { output: output }; } if (!options.window.document.createElement) { assert.log('skipping output tests (missing doc.createElement) for ' + name); return { output: output }; } if (!('output' in expected)) { return { output: output }; } var context = requisition.conversionContext; return output.convert('dom', context).then(function(node) { var actualOutput = node.textContent.trim(); var doTest = function(match, against) { // Only log the real textContent if the test fails if (against.match(match) != null) { assert.ok(true, 'html output for \'' + name + '\' ' + 'should match /' + match.source || match + '/'); } else { assert.ok(false, 'html output for \'' + name + '\' ' + 'should match /' + match.source || match + '/. ' + 'Actual textContent: "' + against + '"'); } }; if (typeof expected.output === 'string') { assert.is(actualOutput, expected.output, 'html output for ' + name); } else if (Array.isArray(expected.output)) { expected.output.forEach(function(match) { doTest(match, actualOutput); }); } else { doTest(expected.output, actualOutput); } if (expected.error) { cli.logErrors = origLogErrors; } return { output: output, text: actualOutput }; }); }.bind(this)).then(function(data) {
exports.exec = function(options, tests) { var requisition = options.display.requisition; var inputter = options.display.inputter; tests = tests || {}; if (tests.typed) { inputter.setInput(tests.typed); } var typed = inputter.getInputState().typed; var output = requisition.exec({ hidden: true }); test.is(typed, output.typed, 'output.command for: ' + typed); if (tests.completed !== false) { test.ok(output.completed, 'output.completed false for: ' + typed); } else { // It is actually an error if we say something is async and it turns // out not to be? For now we're saying 'no' // test.ok(!output.completed, 'output.completed true for: ' + typed); } if (tests.args != null) { test.is(Object.keys(tests.args).length, Object.keys(output.args).length, 'arg count for ' + typed); Object.keys(output.args).forEach(function(arg) { var expectedArg = tests.args[arg]; var actualArg = output.args[arg]; if (Array.isArray(expectedArg)) { if (!Array.isArray(actualArg)) { test.ok(false, 'actual is not an array. ' + typed + '/' + arg); return; } test.is(expectedArg.length, actualArg.length, 'array length: ' + typed + '/' + arg); for (var i = 0; i < expectedArg.length; i++) { test.is(expectedArg[i], actualArg[i], 'member: "' + typed + '/' + arg + '/' + i); } } else { test.is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg); } }); } if (!options.window.document.createElement) { test.log('skipping output tests (missing doc.createElement) for ' + typed); return; } var div = options.window.document.createElement('div'); output.toDom(div); var displayed = div.textContent.trim(); if (tests.outputMatch) { function doTest(match, against) { if (!match.test(against)) { test.ok(false, "html output for " + typed + " against " + match.source); console.log("Actual textContent"); console.log(against); } } if (Array.isArray(tests.outputMatch)) { tests.outputMatch.forEach(function(match) { doTest(match, displayed); }); } else { doTest(tests.outputMatch, displayed); } } if (tests.blankOutput != null) { if (!/^$/.test(displayed)) { test.ok(false, "html for " + typed + " (textContent sent to info)"); console.log("Actual textContent"); console.log(displayed); } } };
var onError = function(ex) { assert.ok(false, assert.currentTest + ': ' + ex); util.errorHandler(ex); onDone(); };
expPredict.forEach(function(p) { contains = predictionsHas(p); test.ok(contains, 'missing prediction ' + p); });
Object.keys(this.tests).forEach(function(testName) { assert.currentTest = this.tests[testName]; assert.ok(false, message); }.bind(this));