Bug 788486 - GCLI rollup bug fix for bugs 786317, 739947, 708984, 786658, 681623, 787712; r=dcamp

This commit is contained in:
Joe Walker 2012-09-07 14:24:58 +01:00
parent b01195a06f
commit 8a2dd8ceb9
2 changed files with 334 additions and 248 deletions

View File

@ -4068,7 +4068,9 @@ exports._empty = [];
*/
exports.setDocument = function(document) {
doc = document;
exports._empty = doc.querySelectorAll('x>:root');
if (doc != null) {
exports._empty = doc.querySelectorAll('x>:root');
}
};
/**
@ -5127,7 +5129,7 @@ var view = require('gcli/ui/view');
var l10n = require('gcli/l10n');
var canon = require('gcli/canon');
var Promise = require('gcli/promise').Promise;
var Q = require('gcli/promise');
var Status = require('gcli/types').Status;
var Conversion = require('gcli/types').Conversion;
@ -5190,8 +5192,6 @@ function Assignment(param, paramIndex) {
this.paramIndex = paramIndex;
this.onAssignmentChange = util.createEvent('Assignment.onAssignmentChange');
this.setBlank();
}
/**
@ -5275,39 +5275,6 @@ Assignment.prototype.isInName = function() {
this.conversion.arg.prefix.slice(-1) !== ' ';
};
/**
* Report on the status of the last parse() conversion.
* We force mutations to happen through this method rather than have
* setValue and setArgument functions to help maintain integrity when we
* have ArrayArguments and don't want to get confused. This way assignments
* are just containers for a conversion rather than things that store
* a connection between an arg/value.
* @see types.Conversion
*/
Assignment.prototype.setConversion = function(conversion) {
var oldConversion = this.conversion;
this.conversion = conversion;
this.conversion.assign(this);
if (this.conversion.equals(oldConversion)) {
return;
}
this.onAssignmentChange({
assignment: this,
conversion: this.conversion,
oldConversion: oldConversion
});
};
/**
* Setup an empty value for the conversion by parsing an empty argument.
*/
Assignment.prototype.setBlank = function() {
this.setConversion(this.param.type.getBlank());
};
/**
* Make sure that there is some content for this argument by using an
* Argument of '' if needed.
@ -5454,8 +5421,6 @@ function CommandAssignment() {
this.param = new canon.Parameter(commandParamMetadata);
this.paramIndex = -1;
this.onAssignmentChange = util.createEvent('CommandAssignment.onAssignmentChange');
this.setBlank();
}
CommandAssignment.prototype = Object.create(Assignment.prototype);
@ -5540,6 +5505,7 @@ function Requisition(environment, doc) {
// The command that we are about to execute.
// @see setCommandConversion()
this.commandAssignment = new CommandAssignment();
this._setAssignment(this.commandAssignment, null, true);
// The object that stores of Assignment objects that we are filling out.
// The Assignment objects are stored under their param.name for named
@ -5626,6 +5592,7 @@ Requisition.prototype._commandAssignmentChanged = function(ev) {
for (var i = 0; i < command.params.length; i++) {
var param = command.params[i];
var assignment = new Assignment(param, i);
this._setAssignment(assignment, null, true);
assignment.onAssignmentChange.add(this._assignmentChanged, this);
this._assignments[param.name] = assignment;
}
@ -5748,40 +5715,81 @@ Requisition.prototype.getAssignments = function(includeCommand) {
};
/**
* Alter the given assignment using the given arg. This function is better than
* calling assignment.setConversion(assignment.param.type.parse(arg)) because
* it adjusts the args in this requisition to keep things up to date
* Alter the given assignment using the given arg.
* @param assignment The assignment to alter
* @param arg The new value for the assignment. An instance of Argument, or an
* instance of Conversion, or null to set the blank value.
*/
Requisition.prototype.setAssignment = function(assignment, arg) {
var originalArgs = assignment.arg.getArgs();
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, false);
};
var replacementArgs = arg.getArgs();
var maxLen = Math.max(originalArgs.length, replacementArgs.length);
for (var i = 0; i < maxLen; i++) {
// If there are no more original args, or if the original arg was blank
// (i.e. not typed by the user), we'll just need to add at the end
if (i >= originalArgs.length || originalArgs[i].type === 'BlankArgument') {
this._args.push(replacementArgs[i]);
continue;
}
/**
* Internal function to alter the given assignment using the given arg.
* @param assignment The assignment to alter
* @param arg The new value for the assignment. An instance of Argument, or an
* instance of Conversion, or null to set the blank value.
* @param skipArgUpdate (default=false) Adjusts the args in this requisition to
* keep things up to date. Args should only be skipped when setAssignment is
* being called as part of the update process.
*/
Requisition.prototype._setAssignment = function(assignment, arg, skipArgUpdate) {
if (!skipArgUpdate) {
var originalArgs = assignment.arg.getArgs();
var index = this._args.indexOf(originalArgs[i]);
if (index === -1) {
console.error('Couldn\'t find ', originalArgs[i], ' in ', this._args);
throw new Error('Couldn\'t find ' + originalArgs[i]);
}
// Update the args array
var replacementArgs = arg.getArgs();
var maxLen = Math.max(originalArgs.length, replacementArgs.length);
for (var i = 0; i < maxLen; i++) {
// If there are no more original args, or if the original arg was blank
// (i.e. not typed by the user), we'll just need to add at the end
if (i >= originalArgs.length || originalArgs[i].type === 'BlankArgument') {
this._args.push(replacementArgs[i]);
continue;
}
// If there are no more replacement args, we just remove the original args
// Otherwise swap original args and replacements
if (i >= replacementArgs.length) {
this._args.splice(index, 1);
}
else {
this._args[index] = replacementArgs[i];
var index = this._args.indexOf(originalArgs[i]);
if (index === -1) {
console.error('Couldn\'t find ', originalArgs[i], ' in ', this._args);
throw new Error('Couldn\'t find ' + originalArgs[i]);
}
// If there are no more replacement args, we just remove the original args
// Otherwise swap original args and replacements
if (i >= replacementArgs.length) {
this._args.splice(index, 1);
}
else {
this._args[index] = replacementArgs[i];
}
}
}
var conversion;
if (arg == null) {
conversion = assignment.param.type.getBlank();
}
else if (typeof arg.getStatus === 'function') {
conversion = arg;
}
else {
conversion = assignment.param.type.parse(arg);
}
var oldConversion = assignment.conversion;
assignment.conversion = conversion;
assignment.conversion.assign(assignment);
if (assignment.conversion.equals(oldConversion)) {
return;
}
assignment.onAssignmentChange({
assignment: assignment,
conversion: assignment.conversion,
oldConversion: oldConversion
});
};
/**
@ -5789,7 +5797,7 @@ Requisition.prototype.setAssignment = function(assignment, arg) {
*/
Requisition.prototype.setBlankArguments = function() {
this.getAssignments().forEach(function(assignment) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
}, this);
};
@ -6148,8 +6156,8 @@ Requisition.prototype.getAssignmentAt = function(cursor) {
* @param input (optional) The command to execute. See above.
*/
Requisition.prototype.exec = function(input) {
var command;
var args;
var command = null;
var args = null;
var hidden = false;
if (input && input.hidden) {
hidden = true;
@ -6200,33 +6208,58 @@ Requisition.prototype.exec = function(input) {
this.commandOutputManager.onOutput({ output: output });
var onDone = function(data) {
output.complete(data);
};
var onError = function(error) {
console.error(error);
output.error = true;
output.complete(error);
};
try {
var context = exports.createExecutionContext(this);
var reply = command.exec(args, context);
if (reply != null && typeof reply.then === 'function') {
reply.then(
function(data) { output.complete(data); },
function(error) { output.error = true; output.complete(error); });
output.promise = reply;
// Add progress to our promise and add a handler for it here
// See bug 659300
}
else {
output.complete(reply);
}
this._then(reply, onDone, onError);
}
catch (ex) {
console.error(ex);
output.error = true;
output.complete(ex);
onError(ex);
}
this.update('');
return output;
};
/**
* Different types of promise have different ways of doing 'then'. This is a
* catch-all so we can ignore the differences. It also handles concrete values
* and calls onDone directly if thing is not a promise.
* @param thing The value to test for 'promiseness'
* @param onDone The action to take if thing is resolved
* @param onError The action to take if thing is rejected
*/
Requisition.prototype._then = function(thing, onDone, onError) {
var then = null;
if (thing != null && typeof thing.then === 'function') {
// Old GCLI style / simple promises with a then function
then = thing.then;
}
else if (thing != null && thing.promise != null &&
typeof thing.promise.then === 'function') {
// Q / Mozilla add-ons style
then = thing.promise.then;
}
if (then != null) {
then(onDone, onError);
}
else {
onDone(thing);
}
};
/**
* Called by the UI when ever the user interacts with a command line input
* @param typed The contents of the input field
@ -6517,7 +6550,7 @@ Requisition.prototype._split = function(args) {
// Special case: if the user enters { console.log('foo'); } then we need to
// use the hidden 'eval' command
conversion = new Conversion(evalCommand, new ScriptArgument());
this.commandAssignment.setConversion(conversion);
this._setAssignment(this.commandAssignment, conversion, true);
return;
}
@ -6525,8 +6558,8 @@ Requisition.prototype._split = function(args) {
while (argsUsed <= args.length) {
var arg = (argsUsed === 1) ?
args[0] :
new MergedArgument(args, 0, argsUsed);
args[0] :
new MergedArgument(args, 0, argsUsed);
conversion = this.commandAssignment.param.type.parse(arg);
// We only want to carry on if this command is a parent command,
@ -6544,7 +6577,7 @@ Requisition.prototype._split = function(args) {
argsUsed++;
}
this.commandAssignment.setConversion(conversion);
this._setAssignment(this.commandAssignment, conversion, true);
for (var i = 0; i < argsUsed; i++) {
args.shift();
@ -6590,11 +6623,8 @@ Requisition.prototype._assign = function(args) {
if (this.assignmentCount === 1) {
var assignment = this.getAssignment(0);
if (assignment.param.type instanceof StringType) {
var arg = (args.length === 1) ?
args[0] :
new MergedArgument(args);
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
var arg = (args.length === 1) ? args[0] : new MergedArgument(args);
this._setAssignment(assignment, arg, true);
return;
}
}
@ -6639,8 +6669,7 @@ Requisition.prototype._assign = function(args) {
arrayArg.addArgument(arg);
}
else {
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, true);
}
}
else {
@ -6657,7 +6686,7 @@ Requisition.prototype._assign = function(args) {
// If not set positionally, and we can't set it non-positionally,
// we have to default it to prevent previous values surviving
if (!assignment.param.isPositionalAllowed) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
return;
}
@ -6674,7 +6703,7 @@ Requisition.prototype._assign = function(args) {
}
else {
if (args.length === 0) {
assignment.setBlank();
this._setAssignment(assignment, null, true);
}
else {
var arg = args.splice(0, 1)[0];
@ -6688,8 +6717,7 @@ Requisition.prototype._assign = function(args) {
this._unassigned.push(new UnassignedAssignment(this, arg));
}
else {
var conversion = assignment.param.type.parse(arg);
assignment.setConversion(conversion);
this._setAssignment(assignment, arg, true);
}
}
}
@ -6698,8 +6726,7 @@ Requisition.prototype._assign = function(args) {
// Now we need to assign the array argument (if any)
Object.keys(arrayArgs).forEach(function(name) {
var assignment = this.getAssignment(name);
var conversion = assignment.param.type.parse(arrayArgs[name]);
assignment.setConversion(conversion);
this._setAssignment(assignment, arrayArgs[name], true);
}, this);
// What's left is can't be assigned, but we need to extract
@ -6729,17 +6756,31 @@ function Output(options) {
}
/**
* Called when there is data to display
* @param data
* Called when there is data to display, but the command is still executing
* @param data The new data. If the data structure has been altered but the
* root object is still the same, The same root object should be passed in the
* data parameter.
* @param ev Optional additional event data, for example to explain how the
* data structure has changed
*/
Output.prototype.complete = function(data) {
Output.prototype.changed = function(data, ev) {
this.data = data;
ev = ev || {};
ev.output = this;
this.onChange(ev);
};
/**
* Called when there is data to display, and the command has finished executing
* See changed() for details on parameters.
*/
Output.prototype.complete = function(data, ev) {
this.end = new Date();
this.duration = this.end.getTime() - this.start.getTime();
this.completed = true;
this.onChange({ output: this });
this.changed(data, ev);
};
/**
@ -6830,8 +6871,15 @@ exports.createExecutionContext = function(requisition) {
document: requisition.document,
environment: requisition.environment,
createView: view.createView,
defer: function() {
return Q.defer();
},
/**
* @deprecated Use defer() instead, which does the same thing, but is not
* confusingly named
*/
createPromise: function() {
return new Promise();
return Q.defer();
}
};
};
@ -6856,8 +6904,13 @@ exports.createExecutionContext = function(requisition) {
define('gcli/promise', ['require', 'exports', 'module' ], function(require, exports, module) {
Components.utils.import("resource:///modules/devtools/Promise.jsm");
exports.Promise = Promise;
var imported = {};
Components.utils.import("resource://gre/modules/commonjs/promise/core.js",
imported);
exports.defer = imported.Promise.defer;
exports.resolve = imported.Promise.resolve;
exports.reject = imported.Promise.reject;
});
define("text!gcli/ui/intro.html", [], "\n" +
@ -7237,7 +7290,7 @@ FocusManager.prototype._checkShow = function() {
if (fire) {
if (this._debug) {
console.debug('FocusManager.onVisibilityChange', ev);
console.log('FocusManager.onVisibilityChange', ev);
}
this.onVisibilityChange(ev);
}
@ -7735,6 +7788,9 @@ Field.prototype.destroy = function() {
delete this.messageElement;
};
// Note: We could/should probably change Fields from working with Conversions
// to working with Arguments (Tokens), which makes for less calls to parse()
/**
* Update this field display with the value from this conversion.
* Subclasses should provide an implementation of this function.
@ -9393,7 +9449,9 @@ Inputter.prototype.textChanged = function() {
input.typed = newStr;
this._processCaretChange(input);
this.element.value = newStr;
if (this.element.value !== newStr) {
this.element.value = newStr;
}
this.onInputChange({ inputState: input });
};
@ -9469,8 +9527,12 @@ Inputter.prototype._processCaretChange = function(input) {
cursor: { start: start, end: end }
};
this.element.selectionStart = start;
this.element.selectionEnd = end;
if (this.element.selectionStart !== start) {
this.element.selectionStart = start;
}
if (this.element.selectionEnd !== end) {
this.element.selectionEnd = end;
}
this._checkAssignment(start);
@ -9605,7 +9667,7 @@ Inputter.prototype.onKeyUp = function(ev) {
// If the user is on a valid value, then we increment the value, but if
// they've typed something that's not right we page through predictions
if (this.assignment.getStatus() === Status.VALID) {
this.requisition.increment(assignment);
this.requisition.increment(this.assignment);
// See notes on focusManager.onInputChange in onKeyDown
if (this.focusManager) {
this.focusManager.onInputChange();
@ -9629,7 +9691,7 @@ Inputter.prototype.onKeyUp = function(ev) {
else {
// See notes above for the UP key
if (this.assignment.getStatus() === Status.VALID) {
this.requisition.decrement(assignment);
this.requisition.decrement(this.assignment);
// See notes on focusManager.onInputChange in onKeyDown
if (this.focusManager) {
this.focusManager.onInputChange();
@ -10314,7 +10376,7 @@ Tooltip.prototype.selectChoice = function(ev) {
* Called by the onFieldChange event on the current Field
*/
Tooltip.prototype.fieldChanged = function(ev) {
this.assignment.setConversion(ev.conversion);
this.requisition.setAssignment(this.assignment, ev.conversion.arg);
var isError = ev.conversion.message != null && ev.conversion.message !== '';
this.focusManager.setError(isError);

View File

@ -108,8 +108,8 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
* @param options Lookup of options that customize test running. Includes:
* - window (default=undefined) A reference to the DOM window. If left
* undefined then a reduced set of tests will run.
* - isNode (default=false) Are we running under NodeJS, specifically, are we
* using JSDom, which isn't a 100% complete DOM implementation.
* - isJsdom (default=false) Are we running under JSDom, specifically, which
* isn't a 100% complete DOM implementation.
* Some tests are skipped when using NodeJS.
* - display (default=undefined) A reference to a Display implementation.
* A reduced set of tests will run if left undefined
@ -119,12 +119,12 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
* |requisition.exec()| which prevents the display from becoming messed up,
* however use of hideExec restricts the set of tests that are run
*/
exports.run = function(options) {
exports.runAsync = function(options, callback) {
options = options || {};
examiner.mergeDefaultOptions(options);
examiner.reset();
examiner.run(options);
examiner.runAsync(options, callback);
// A better set of default than those specified above, come from the set
// that are passed to run().
@ -155,13 +155,6 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
// setTimeout keeps stack traces clear of RequireJS frames
window.setTimeout(function() {
var options = {
window: window,
display: window.display,
hideExec: true
};
exports.run(options);
window.createDebugCheck = function() {
require([ 'gclitest/helpers' ], function(helpers) {
helpers.setup(options);
@ -198,7 +191,15 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite', 'gc
mockCommands.setup();
});
};
window.testCommands();
var options = {
window: window,
display: window.display,
hideExec: true
};
exports.runAsync(options, function() {
window.testCommands();
});
}, 10);
return {
@ -326,25 +327,6 @@ examiner.mergeDefaultOptions = function(options) {
});
};
/**
* Run the tests defined in the test suite synchronously
*/
examiner.run = function(options) {
Object.keys(examiner.suites).forEach(function(suiteName) {
var suite = examiner.suites[suiteName];
suite.run(options);
}.bind(this));
if (options.detailedResultLog) {
examiner.detailedResultLog();
}
else {
console.log('Completed test suite');
}
return examiner.suites;
};
/**
* Run all the tests asynchronously
*/
@ -477,21 +459,6 @@ Suite.prototype.reset = function() {
}, this);
};
/**
* Run all the tests in this suite synchronously
*/
Suite.prototype.run = function(options) {
if (!this._setup(options)) {
return;
}
Object.keys(this.tests).forEach(function(testName) {
this.tests[testName].run(options);
}, this);
this._shutdown(options);
};
/**
* Run all the tests in this suite asynchronously
*/
@ -636,6 +603,9 @@ function Test(suite, name, func) {
this.func = func;
this.title = name.replace(/^test/, '').replace(/([A-Z])/g, ' $1');
this.outstanding = [];
this.callback = undefined;
this.failures = [];
this.status = stati.notrun;
this.checks = 0;
@ -645,16 +615,20 @@ function Test(suite, name, func) {
* Reset the test to its original state
*/
Test.prototype.reset = function() {
this.outstanding = [];
this.callback = undefined;
this.failures = [];
this.status = stati.notrun;
this.checks = 0;
};
/**
* Run just a single test
* Run all the tests in this suite asynchronously
*/
Test.prototype.run = function(options) {
Test.prototype.runAsync = function(options, callback) {
assert.currentTest = this;
this.callback = callback;
this.status = stati.executing;
this.failures = [];
this.checks = 0;
@ -675,18 +649,20 @@ Test.prototype.run = function(options) {
}
assert.currentTest = null;
this.checkFinish();
};
/**
* Run all the tests in this suite asynchronously
* Check to see if the currently executing test is completed (i.e. the list of
* outstanding tasks has all been completed)
*/
Test.prototype.runAsync = function(options, callback) {
setTimeout(function() {
this.run(options);
if (typeof callback === 'function') {
callback();
Test.prototype.checkFinish = function() {
if (this.outstanding.length == 0) {
if (typeof this.callback === 'function') {
this.callback();
}
}.bind(this), delay);
}
};
/**
@ -892,21 +868,25 @@ define('gclitest/testCanon', ['require', 'exports', 'module' , 'gclitest/helpers
* limitations under the License.
*/
define('gclitest/helpers', ['require', 'exports', 'module' , 'test/assert', 'gcli/util'], function(require, exports, module) {
define('gclitest/helpers', ['require', 'exports', 'module' , 'test/assert'], function(require, exports, module) {
var test = require('test/assert');
var util = require('gcli/util');
// A copy of this code exists in firefox mochitests; when updated here it
// should be updated there too. Hence the use of an exports synonym for non
// AMD contexts.
var helpers = exports;
helpers._display = undefined;
helpers._options = undefined;
helpers.setup = function(options) {
helpers._options = options;
helpers._display = options.display;
};
helpers.shutdown = function(options) {
helpers._options = undefined;
helpers._display = undefined;
};
@ -1025,6 +1005,16 @@ helpers.setInput = function(typed, cursor) {
if (cursor) {
helpers._display.inputter.setCursor({ start: cursor, end: cursor });
}
else {
// This is a hack because jsdom appears to not handle cursor updates
// in the same way as most browsers.
if (helpers._options.isJsdom) {
helpers._display.inputter.setCursor({
start: typed.length,
end: typed.length
});
}
}
helpers._display.focusManager.onInputChange();
};
@ -1589,7 +1579,7 @@ exports.testElement = function(options) {
test.ok(assign1.arg.type === 'BlankArgument');
test.is(undefined, assign1.value);
if (!options.isNode) {
if (!options.isJsdom) {
update({ typed: 'tse :root', cursor: { start: 9, end: 9 } });
test.is( 'VVVVVVVVV', statuses);
test.is(Status.VALID, status);
@ -1625,7 +1615,7 @@ exports.testElement = function(options) {
test.is(undefined, assign1.value);
}
else {
test.log('Skipping :root test due to jsdom (from isNode)');
test.log('Skipping :root test due to jsdom');
}
update({ typed: 'tse #', cursor: { start: 5, end: 5 } });
@ -2774,9 +2764,10 @@ var mockDoc = {
* http://opensource.org/licenses/BSD-3-Clause
*/
define('gclitest/testFocus', ['require', 'exports', 'module' , 'gclitest/helpers', 'gclitest/mockCommands'], function(require, exports, module) {
define('gclitest/testFocus', ['require', 'exports', 'module' , 'test/assert', 'gclitest/helpers', 'gclitest/mockCommands'], function(require, exports, module) {
var test = require('test/assert');
var helpers = require('gclitest/helpers');
var mockCommands = require('gclitest/mockCommands');
@ -2791,6 +2782,11 @@ exports.shutdown = function(options) {
};
exports.testBasic = function(options) {
if (options.isJsdom) {
test.log('jsdom does not pass on focus events properly, skipping testBasic');
return;
}
helpers.focusInput();
helpers.exec(options, 'help');
@ -3470,10 +3466,11 @@ exports.testHidden = function(options) {
* limitations under the License.
*/
define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers', 'test/assert'], function(require, exports, module) {
define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers', 'test/assert', 'gcli/canon'], function(require, exports, module) {
var helpers = require('gclitest/helpers');
var test = require('test/assert');
var canon = require('gcli/canon');
exports.setup = function(options) {
helpers.setup(options);
@ -3484,8 +3481,8 @@ define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers
};
exports.testIntroStatus = function(options) {
if (options.isFirefox) {
test.log('Skipping testIntroStatus in Firefox.');
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
@ -3507,8 +3504,8 @@ define('gclitest/testIntro', ['require', 'exports', 'module' , 'gclitest/helpers
};
exports.testIntroExec = function(options) {
if (options.isFirefox) {
test.log('Skipping testIntroExec in Firefox.');
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
@ -3683,7 +3680,10 @@ exports.testBasic = function(options) {
input('{ document.title');
check('VVVVVVVVVVVVVVVV', Status.VALID, 'document.title', 0);
test.ok('donteval' in options.window, 'donteval exists');
if (!options.isJsdom) {
// jsdom causes an eval here, maybe that's node/v8?
test.ok('donteval' in options.window, 'donteval exists');
}
input('{ don');
check('VVIII', Status.ERROR, 'don', 'donteval');
@ -3832,12 +3832,12 @@ exports.testComplete = function(options) {
check('{ wind', COMPLETES_TO, '{ window', 0);
check('{ window.docum', COMPLETES_TO, '{ window.document', 0);
// Bug 717228: This fails under node
if (!options.isNode) {
// Bug 717228: This fails under jsdom
if (!options.isJsdom) {
check('{ window.document.titl', COMPLETES_TO, '{ window.document.title ', 0);
}
else {
test.log('Running under Node. Skipping tests due to bug 717228.');
test.log('Skipping tests due to jsdom and bug 717228.');
}
}
};
@ -4008,61 +4008,66 @@ exports.testNode = function(options) {
}
});
helpers.setInput('tse :root');
helpers.check({
input: 'tse :root',
hints: ' [options]',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
if (options.isJsdom) {
test.log('skipping node tests because jsdom');
}
else {
helpers.setInput('tse :root');
helpers.check({
input: 'tse :root',
hints: ' [options]',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse :root ');
helpers.check({
input: 'tse :root ',
hints: '[options]',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root ', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
test.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
helpers.setInput('tse :root ');
helpers.check({
input: 'tse :root ',
hints: '[options]',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'node',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root ', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
test.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
helpers.setInput('tse #gcli-nomatch');
helpers.check({
input: 'tse #gcli-nomatch',
hints: ' [options]',
markup: 'VVVVIIIIIIIIIIIII',
cursor: 17,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #gcli-nomatch',
status: 'INCOMPLETE',
message: 'No matches'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse #gcli-nomatch');
helpers.check({
input: 'tse #gcli-nomatch',
hints: ' [options]',
markup: 'VVVVIIIIIIIIIIIII',
cursor: 17,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #gcli-nomatch',
status: 'INCOMPLETE',
message: 'No matches'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
}
helpers.setInput('tse #');
helpers.check({
@ -4131,6 +4136,11 @@ exports.testNode = function(options) {
exports.testNodes = function(options) {
var requisition = options.display.requisition;
if (options.isJsdom) {
test.log('skipping node tests because jsdom');
return;
}
helpers.setInput('tse :root --nodes *');
helpers.check({
input: 'tse :root --nodes *',
@ -4236,13 +4246,14 @@ exports.testNodes = function(options) {
* limitations under the License.
*/
define('gclitest/testPref', ['require', 'exports', 'module' , 'gcli/commands/pref', 'gclitest/helpers', 'gclitest/mockSettings', 'test/assert'], function(require, exports, module) {
define('gclitest/testPref', ['require', 'exports', 'module' , 'gcli/commands/pref', 'gclitest/helpers', 'gclitest/mockSettings', 'test/assert', 'gcli/canon'], function(require, exports, module) {
var pref = require('gcli/commands/pref');
var helpers = require('gclitest/helpers');
var mockSettings = require('gclitest/mockSettings');
var test = require('test/assert');
var canon = require('gcli/canon');
exports.setup = function(options) {
@ -4270,6 +4281,11 @@ exports.testPrefShowStatus = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
helpers.setInput('pref s');
helpers.check({
typed: 'pref s',
@ -4333,6 +4349,11 @@ exports.testPrefSetStatus = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
helpers.setInput('pref s');
helpers.check({
typed: 'pref s',
@ -4395,6 +4416,11 @@ exports.testPrefExec = function(options) {
return;
}
if (canon.getCommand('intro') == null) {
test.log('Skipping testIntroStatus; missing intro command.');
return;
}
var initialAllowSet = pref.allowSet.value;
pref.allowSet.value = false;
@ -4744,12 +4770,11 @@ exports.testPredictions = function(options) {
var resource3 = types.getType({ name: 'resource', include: 'text/css' });
var options3 = resource3.getLookup();
// jsdom fails to support digging into stylesheets
if (!options.isNode) {
if (!options.isJsdom) {
test.ok(options3.length >= 1, 'have resources');
}
else {
test.log('Running under Node. ' +
'Skipping checks due to jsdom document.stylsheets support.');
test.log('Skipping checks due to jsdom document.stylsheets support.');
}
options3.forEach(function(prediction) {
checkPrediction(resource3, prediction);
@ -5458,7 +5483,7 @@ function type(typed, tests, options) {
inputter.setCursor({ start: tests.cursor, end: tests.cursor });
}
if (!options.isNode) {
if (!options.isJsdom) {
if (tests.important) {
test.ok(tooltip.field.isImportant, 'Important for ' + typed);
}
@ -5488,8 +5513,8 @@ exports.testActivate = function(options) {
return;
}
if (options.isNode) {
test.log('Running under Node. Reduced checks due to JSDom.textContent');
if (options.isJsdom) {
test.log('Reduced checks due to JSDom.textContent');
}
type(' ', { }, options);
@ -5572,9 +5597,8 @@ function forEachType(options, callback) {
}
exports.testDefault = function(options) {
if (options.isNode) {
test.log('Running under Node. ' +
'Skipping tests due to issues with resource type.');
if (options.isJsdom) {
test.log('Skipping tests due to issues with resource type.');
return;
}