/* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ /* * * * * * * * *********************************** WARNING *********************************** * * Do not edit this file without understanding where it comes from, * Your changes are likely to be overwritten without warning. * * This test file is generated using a level 25 wizard spell cast on the * test files that run in the browser as part of GCLI's test suite. * For details of how to cast the spell, see GCLI's gcli.js * * For more information on GCLI see: * - https://github.com/mozilla/gcli/blob/master/docs/index.md * - https://wiki.mozilla.org/DevTools/Features/GCLI * * The original source for this file is: * https://github.com/mozilla/gcli/ * ******************************************************************************* * * * * * * * * * */ /////////////////////////////////////////////////////////////////////////////// /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/index', ['require', 'exports', 'module' , 'gclitest/suite'], function(require, exports, module) { var examiner = require('gclitest/suite').examiner; // A minimum fake dom to get us through the JS tests var fakeWindow = { isFake: true, document: { title: 'Fake DOM' } }; fakeWindow.window = fakeWindow; examiner.defaultOptions = { window: fakeWindow, hideExec: true }; /** * A simple proxy to examiner.run, for convenience - this is run from the * top level. * @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. * 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 * - detailedResultLog (default=false) do we output a test summary to * |console.log| on test completion. * - hideExec (default=false) Set the |hidden| property in calls to * |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) { examiner.run(options || {}); // A better set of default than those specified above, come from the set // that are passed to run(). examiner.defaultOptions = { window: options.window, display: options.display, hideExec: options.hideExec }; }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testCli', 'gclitest/testCompletion', 'gclitest/testExec', 'gclitest/testHistory', 'gclitest/testJs', 'gclitest/testKeyboard', 'gclitest/testRequire', 'gclitest/testResource', 'gclitest/testScratchpad', 'gclitest/testSpell', 'gclitest/testSplit', 'gclitest/testTokenize', 'gclitest/testTooltip', 'gclitest/testTypes', 'gclitest/testUtil'], function(require, exports, module) { // We need to make sure GCLI is initialized before we begin testing it require('gcli/index'); var examiner = require('test/examiner'); // It's tempting to want to unify these strings and make addSuite() do the // call to require(), however that breaks the build system which looks for // the strings passed to require examiner.addSuite('gclitest/testCli', require('gclitest/testCli')); examiner.addSuite('gclitest/testCompletion', require('gclitest/testCompletion')); examiner.addSuite('gclitest/testExec', require('gclitest/testExec')); examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory')); examiner.addSuite('gclitest/testJs', require('gclitest/testJs')); examiner.addSuite('gclitest/testKeyboard', require('gclitest/testKeyboard')); examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire')); examiner.addSuite('gclitest/testResource', require('gclitest/testResource')); examiner.addSuite('gclitest/testScratchpad', require('gclitest/testScratchpad')); examiner.addSuite('gclitest/testSpell', require('gclitest/testSpell')); examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit')); examiner.addSuite('gclitest/testTokenize', require('gclitest/testTokenize')); examiner.addSuite('gclitest/testTooltip', require('gclitest/testTooltip')); examiner.addSuite('gclitest/testTypes', require('gclitest/testTypes')); examiner.addSuite('gclitest/testUtil', require('gclitest/testUtil')); exports.examiner = examiner; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('test/examiner', ['require', 'exports', 'module' ], function(require, exports, module) { var examiner = exports; /** * Test harness data */ examiner.suites = {}; /** * The gap between tests when running async */ var delay = 10; var currentTest = null; var stati = { notrun: { index: 0, name: 'Skipped' }, executing: { index: 1, name: 'Executing' }, asynchronous: { index: 2, name: 'Waiting' }, pass: { index: 3, name: 'Pass' }, fail: { index: 4, name: 'Fail' } }; /** * Add a test suite. Generally used like: * test.addSuite('foo', require('path/to/foo')); */ examiner.addSuite = function(name, suite) { examiner.suites[name] = new Suite(name, suite); }; /** * When run from an command, there are some options that we can't (and * shouldn't) specify, so we allow a set of default options, which are merged * with the specified options in |run()|. */ examiner.defaultOptions = {}; /** * Add properties to |options| from |examiner.defaultOptions| when |options| * does not have a value for a given name. */ function mergeDefaultOptions(options) { Object.keys(examiner.defaultOptions).forEach(function(name) { if (options[name] == null) { options[name] = examiner.defaultOptions[name]; } }); } /** * Run the tests defined in the test suite synchronously */ examiner.run = function(options) { mergeDefaultOptions(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 */ examiner.runAsync = function(options, callback) { mergeDefaultOptions(options); this._runAsyncInternal(0, options, callback); }; /** * Run all the test suits asynchronously */ examiner._runAsyncInternal = function(i, options, callback) { if (i >= Object.keys(examiner.suites).length) { if (typeof callback === 'function') { callback(); } return; } var suiteName = Object.keys(examiner.suites)[i]; examiner.suites[suiteName].runAsync(options, function() { setTimeout(function() { examiner._runAsyncInternal(i + 1, options, callback); }.bind(this), delay); }.bind(this)); }; /** * Create a JSON object suitable for serialization */ examiner.toRemote = function() { return { suites: Object.keys(examiner.suites).map(function(suiteName) { return examiner.suites[suiteName].toRemote(); }.bind(this)), summary: { checks: this.checks, status: this.status } }; }; /** * The number of checks in this set of test suites is the sum of the checks in * the test suites. */ Object.defineProperty(examiner, 'checks', { get: function() { return Object.keys(examiner.suites).reduce(function(current, suiteName) { return current + examiner.suites[suiteName].checks; }.bind(this), 0); }, enumerable: true }); /** * The status of this set of test suites is the worst of the statuses of the * contained test suites. */ Object.defineProperty(examiner, 'status', { get: function() { return Object.keys(examiner.suites).reduce(function(status, suiteName) { var suiteStatus = examiner.suites[suiteName].status; return status.index > suiteStatus.index ? status : suiteStatus; }.bind(this), stati.notrun); }, enumerable: true }); /** * Output a test summary to console.log */ examiner.detailedResultLog = function() { Object.keys(this.suites).forEach(function(suiteName) { var suite = examiner.suites[suiteName]; console.log(suite.name + ': ' + suite.status.name + ' (funcs=' + Object.keys(suite.tests).length + ', checks=' + suite.checks + ')'); Object.keys(suite.tests).forEach(function(testName) { var test = suite.tests[testName]; if (test.status !== stati.pass || test.failures.length !== 0) { console.log('- ' + test.name + ': ' + test.status.name); test.failures.forEach(function(failure) { console.log(' - ' + failure.message); if (failure.expected) { console.log(' - Expected: ' + failure.expected); console.log(' - Actual: ' + failure.actual); } }.bind(this)); } }.bind(this)); }.bind(this)); console.log(); console.log('Summary: ' + this.status.name + ' (' + this.checks + ' checks)'); }; /** * Used by assert to record a failure against the current test * @param failure A set of properties describing the failure. Properties include: * - message (string, required) A message describing the test * - expected (optional) The expected data * - actual (optional) The actual data */ examiner.recordFailure = function(failure) { if (!currentTest) { console.error('No currentTest for ' + failure.message); return; } currentTest.status = stati.fail; currentTest.failures.push(failure); }; /** * Used by assert to record a check pass */ examiner.recordPass = function() { if (!currentTest) { console.error('No currentTest'); return; } currentTest.checks++; }; /** * When we want to note something alongside a test */ examiner.log = function(message) { currentTest.failures.push({ message: message }); }; /** * A suite is a group of tests */ function Suite(suiteName, suite) { this.name = suiteName.replace(/gclitest\//, ''); this.suite = suite; this.tests = {}; Object.keys(suite).forEach(function(testName) { if (testName !== 'setup' && testName !== 'shutdown') { var test = new Test(this, testName, suite[testName]); this.tests[testName] = test; } }.bind(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) { var test = this.tests[testName]; test.run(options); }.bind(this)); this._shutdown(options); }; /** * Run all the tests in this suite asynchronously */ Suite.prototype.runAsync = function(options, callback) { if (!this._setup(options)) { if (typeof callback === 'function') { callback(); } return; } this._runAsyncInternal(0, options, function() { this._shutdown(options); if (typeof callback === 'function') { callback(); } }.bind(this)); }; /** * Function used by the async runners that can handle async recursion. */ Suite.prototype._runAsyncInternal = function(i, options, callback) { if (i >= Object.keys(this.tests).length) { if (typeof callback === 'function') { callback(); } return; } var testName = Object.keys(this.tests)[i]; this.tests[testName].runAsync(options, function() { setTimeout(function() { this._runAsyncInternal(i + 1, options, callback); }.bind(this), delay); }.bind(this)); }; /** * Create a JSON object suitable for serialization */ Suite.prototype.toRemote = function() { return { name: this.name, tests: Object.keys(this.tests).map(function(testName) { return this.tests[testName].toRemote(); }.bind(this)) }; }; /** * The number of checks in this suite is the sum of the checks in the contained * tests. */ Object.defineProperty(Suite.prototype, 'checks', { get: function() { return Object.keys(this.tests).reduce(function(prevChecks, testName) { return prevChecks + this.tests[testName].checks; }.bind(this), 0); }, enumerable: true }); /** * The status of a test suite is the worst of the statuses of the contained * tests. */ Object.defineProperty(Suite.prototype, 'status', { get: function() { return Object.keys(this.tests).reduce(function(prevStatus, testName) { var suiteStatus = this.tests[testName].status; return prevStatus.index > suiteStatus.index ? prevStatus : suiteStatus; }.bind(this), stati.notrun); }, enumerable: true }); /** * Defensively setup the test suite */ Suite.prototype._setup = function(options) { if (typeof this.suite.setup !== 'function') { return true; } try { this.suite.setup(options); return true; } catch (ex) { this._logToAllTests(stati.notrun, '' + ex); console.error(ex); if (ex.stack) { console.error(ex.stack); } return false; } }; /** * Defensively shutdown the test suite */ Suite.prototype._shutdown = function(options) { if (typeof this.suite.shutdown !== 'function') { return true; } try { this.suite.shutdown(options); return true; } catch (ex) { this._logToAllTests(stati.fail, '' + ex); console.error(ex); if (ex.stack) { console.error(ex.stack); } return false; } }; /** * Something has gone wrong that affects all tests in this Suite */ Suite.prototype._logToAllTests = function(status, message) { Object.keys(this.tests).forEach(function(testName) { var test = this.tests[testName]; test.status = status; test.failures.push({ message: message }); }.bind(this)); }; /** * A test represents data about a single test function */ function Test(suite, name, func) { this.suite = suite; this.name = name; this.func = func; this.title = name.replace(/^test/, '').replace(/([A-Z])/g, ' $1'); this.failures = []; this.status = stati.notrun; this.checks = 0; } /** * Run just a single test */ Test.prototype.run = function(options) { currentTest = this; this.status = stati.executing; this.failures = []; this.checks = 0; try { this.func.apply(this.suite, [ options ]); } catch (ex) { this.status = stati.fail; this.failures.push({ message: '' + ex }); console.error(ex); if (ex.stack) { console.error(ex.stack); } } if (this.status === stati.executing) { this.status = stati.pass; } currentTest = null; }; /** * Run all the tests in this suite asynchronously */ Test.prototype.runAsync = function(options, callback) { setTimeout(function() { this.run(options); if (typeof callback === 'function') { callback(); } }.bind(this), delay); }; /** * Create a JSON object suitable for serialization */ Test.prototype.toRemote = function() { return { name: this.name, title: this.title, status: this.status, failures: this.failures, checks: this.checks }; }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testCli', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/types', 'gclitest/commands', 'test/assert'], function(require, exports, module) { var Requisition = require('gcli/cli').Requisition; var Status = require('gcli/types').Status; var commands = require('gclitest/commands'); var test = require('test/assert'); exports.setup = function() { commands.setup(); }; exports.shutdown = function() { commands.shutdown(); }; var assign1; var assign2; var assignC; var requ; var debug = false; var status; var statuses; function update(input) { if (!requ) { requ = new Requisition(); } requ.update(input.typed); if (debug) { console.log('####### TEST: typed="' + input.typed + '" cur=' + input.cursor.start + ' cli=', requ); } status = requ.getStatus(); assignC = requ.getAssignmentAt(input.cursor.start); statuses = requ.getInputStatusMarkup(input.cursor.start).map(function(s) { return Array(s.string.length + 1).join(s.status.toString()[0]); }).join(''); if (requ.commandAssignment.value) { assign1 = requ.getAssignment(0); assign2 = requ.getAssignment(1); } else { assign1 = undefined; assign2 = undefined; } } function verifyPredictionsContains(name, predictions) { return predictions.every(function(prediction) { return name === prediction.name; }, this); } exports.testBlank = function() { update({ typed: '', cursor: { start: 0, end: 0 } }); test.is( '', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is(undefined, requ.commandAssignment.value); update({ typed: ' ', cursor: { start: 1, end: 1 } }); test.is( 'V', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is(undefined, requ.commandAssignment.value); update({ typed: ' ', cursor: { start: 0, end: 0 } }); test.is( 'V', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is(undefined, requ.commandAssignment.value); }; 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); verifyPredictionsContains('tsv', assignC.getPredictions()); verifyPredictionsContains('tsr', assignC.getPredictions()); test.is(undefined, requ.commandAssignment.value); }; exports.testIncompleteSingleMatch = function() { update({ typed: 'tselar', cursor: { start: 6, end: 6 } }); test.is( 'IIIIII', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is(1, assignC.getPredictions().length); test.is('tselarr', assignC.getPredictions()[0].name); test.is(undefined, requ.commandAssignment.value); }; exports.testTsv = function() { update({ typed: 'tsv', cursor: { start: 3, end: 3 } }); test.is( 'VVV', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is('tsv', requ.commandAssignment.value.name); update({ typed: 'tsv ', cursor: { start: 4, end: 4 } }); test.is( 'VVVV', statuses); test.is(Status.ERROR, status); test.is(0, assignC.paramIndex); test.is('tsv', requ.commandAssignment.value.name); update({ typed: 'tsv ', cursor: { start: 2, end: 2 } }); test.is( 'VVVV', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is('tsv', requ.commandAssignment.value.name); update({ typed: 'tsv o', cursor: { start: 5, end: 5 } }); test.is( 'VVVVI', statuses); test.is(Status.ERROR, status); test.is(0, assignC.paramIndex); test.ok(assignC.getPredictions().length >= 2); test.is(commands.option1, assignC.getPredictions()[0].value); test.is(commands.option2, assignC.getPredictions()[1].value); test.is('tsv', requ.commandAssignment.value.name); test.is('o', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsv option', cursor: { start: 10, end: 10 } }); test.is( 'VVVVIIIIII', statuses); test.is(Status.ERROR, status); test.is(0, assignC.paramIndex); test.ok(assignC.getPredictions().length >= 2); test.is(commands.option1, assignC.getPredictions()[0].value); test.is(commands.option2, assignC.getPredictions()[1].value); test.is('tsv', requ.commandAssignment.value.name); test.is('option', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsv option', cursor: { start: 1, end: 1 } }); test.is( 'VVVVEEEEEE', statuses); test.is(Status.ERROR, status); test.is(-1, assignC.paramIndex); test.is('tsv', requ.commandAssignment.value.name); test.is('option', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsv option ', cursor: { start: 11, end: 11 } }); test.is( 'VVVVEEEEEEV', statuses); test.is(Status.ERROR, status); test.is(1, assignC.paramIndex); test.is(0, assignC.getPredictions().length); test.is('tsv', requ.commandAssignment.value.name); test.is('option', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsv option1', cursor: { start: 11, end: 11 } }); test.is( 'VVVVVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsv', requ.commandAssignment.value.name); test.is('option1', assign1.arg.text); test.is(commands.option1, assign1.value); test.is(0, assignC.paramIndex); update({ typed: 'tsv option1 ', cursor: { start: 12, end: 12 } }); test.is( 'VVVVVVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsv', requ.commandAssignment.value.name); test.is('option1', assign1.arg.text); test.is(commands.option1, assign1.value); test.is(1, assignC.paramIndex); update({ typed: 'tsv option1 6', cursor: { start: 13, end: 13 } }); test.is( 'VVVVVVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tsv', requ.commandAssignment.value.name); test.is('option1', assign1.arg.text); test.is(commands.option1, assign1.value); test.is('6', assign2.arg.text); test.is('6', assign2.value); test.is('string', typeof assign2.value); test.is(1, assignC.paramIndex); update({ typed: 'tsv option2 6', cursor: { start: 13, end: 13 } }); test.is( 'VVVVVVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tsv', requ.commandAssignment.value.name); test.is('option2', assign1.arg.text); test.is(commands.option2, assign1.value); test.is('6', assign2.arg.text); test.is(6, assign2.value); test.is('number', typeof assign2.value); test.is(1, assignC.paramIndex); }; exports.testInvalid = function() { update({ typed: 'zxjq', cursor: { start: 4, end: 4 } }); test.is( 'EEEE', statuses); test.is('zxjq', requ.commandAssignment.arg.text); test.is('', requ._unassigned.arg.text); test.is(-1, assignC.paramIndex); update({ typed: 'zxjq ', cursor: { start: 5, end: 5 } }); test.is( 'EEEEV', statuses); test.is('zxjq', requ.commandAssignment.arg.text); test.is('', requ._unassigned.arg.text); test.is(-1, assignC.paramIndex); update({ typed: 'zxjq one', cursor: { start: 8, end: 8 } }); test.is( 'EEEEVEEE', statuses); test.is('zxjq', requ.commandAssignment.arg.text); test.is('one', requ._unassigned.arg.text); }; exports.testSingleString = function() { update({ typed: 'tsr', cursor: { start: 3, end: 3 } }); test.is( 'VVV', statuses); test.is(Status.ERROR, status); test.is('tsr', requ.commandAssignment.value.name); test.ok(assign1.arg.isBlank()); test.is(undefined, assign1.value); test.is(undefined, assign2); update({ typed: 'tsr ', cursor: { start: 4, end: 4 } }); test.is( 'VVVV', statuses); test.is(Status.ERROR, status); test.is('tsr', requ.commandAssignment.value.name); test.ok(assign1.arg.isBlank()); test.is(undefined, assign1.value); test.is(undefined, assign2); update({ typed: 'tsr h', cursor: { start: 5, end: 5 } }); test.is( 'VVVVV', statuses); test.is(Status.VALID, status); test.is('tsr', requ.commandAssignment.value.name); test.is('h', assign1.arg.text); test.is('h', assign1.value); update({ typed: 'tsr "h h"', cursor: { start: 9, end: 9 } }); test.is( 'VVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tsr', requ.commandAssignment.value.name); test.is('h h', assign1.arg.text); test.is('h h', assign1.value); update({ typed: 'tsr h h h', cursor: { start: 9, end: 9 } }); test.is( 'VVVVVVVVV', statuses); test.is('tsr', requ.commandAssignment.value.name); test.is('h h h', assign1.arg.text); test.is('h h h', assign1.value); }; exports.testSingleNumber = function() { update({ typed: 'tsu', cursor: { start: 3, end: 3 } }); test.is( 'VVV', statuses); test.is(Status.ERROR, status); test.is('tsu', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsu ', cursor: { start: 4, end: 4 } }); test.is( 'VVVV', statuses); test.is(Status.ERROR, status); test.is('tsu', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsu 1', cursor: { start: 5, end: 5 } }); test.is( 'VVVVV', statuses); test.is(Status.VALID, status); test.is('tsu', requ.commandAssignment.value.name); test.is('1', assign1.arg.text); test.is(1, assign1.value); test.is('number', typeof assign1.value); update({ typed: 'tsu x', cursor: { start: 5, end: 5 } }); test.is( 'VVVVE', statuses); test.is(Status.ERROR, status); test.is('tsu', requ.commandAssignment.value.name); test.is('x', assign1.arg.text); test.is(undefined, assign1.value); }; exports.testElement = function(options) { update({ typed: 'tse', cursor: { start: 3, end: 3 } }); test.is( 'VVV', statuses); test.is(Status.ERROR, status); test.is('tse', requ.commandAssignment.value.name); test.ok(assign1.arg.isBlank()); test.is(undefined, assign1.value); update({ typed: 'tse :root', cursor: { start: 9, end: 9 } }); test.is( 'VVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tse', requ.commandAssignment.value.name); test.is(':root', assign1.arg.text); if (!options.window.isFake) { test.is(options.window.document.documentElement, assign1.value); } if (!options.window.isFake) { var inputElement = options.window.document.getElementById('gcli-input'); if (inputElement) { update({ typed: 'tse #gcli-input', cursor: { start: 15, end: 15 } }); test.is( 'VVVVVVVVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tse', requ.commandAssignment.value.name); test.is('#gcli-input', assign1.arg.text); test.is(inputElement, assign1.value); } else { test.log('Skipping test that assumes gcli on the web'); } } update({ typed: 'tse #gcli-nomatch', cursor: { start: 17, end: 17 } }); // This is somewhat debatable because this input can't be corrected simply // by typing so it's and error rather than incomplete, however without // digging into the CSS engine we can't tell that so we default to incomplete test.is( 'VVVVIIIIIIIIIIIII', statuses); test.is(Status.ERROR, status); test.is('tse', requ.commandAssignment.value.name); test.is('#gcli-nomatch', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tse #', cursor: { start: 5, end: 5 } }); test.is( 'VVVVE', statuses); test.is(Status.ERROR, status); test.is('tse', requ.commandAssignment.value.name); test.is('#', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tse .', cursor: { start: 5, end: 5 } }); test.is( 'VVVVE', statuses); test.is(Status.ERROR, status); test.is('tse', requ.commandAssignment.value.name); test.is('.', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tse *', cursor: { start: 5, end: 5 } }); test.is( 'VVVVE', statuses); test.is(Status.ERROR, status); test.is('tse', requ.commandAssignment.value.name); test.is('*', assign1.arg.text); test.is(undefined, assign1.value); }; exports.testNestedCommand = function() { update({ typed: 'tsn', cursor: { start: 3, end: 3 } }); test.is( 'III', statuses); test.is(Status.ERROR, status); test.is('tsn', requ.commandAssignment.arg.text); test.is(undefined, assign1); update({ typed: 'tsn ', cursor: { start: 4, end: 4 } }); test.is( 'IIIV', statuses); test.is(Status.ERROR, status); test.is('tsn', requ.commandAssignment.arg.text); test.is(undefined, assign1); update({ typed: 'tsn x', cursor: { start: 5, end: 5 } }); // Commented out while we try out fuzzy matching // test.is( 'EEEVE', statuses); test.is(Status.ERROR, status); test.is('tsn x', requ.commandAssignment.arg.text); test.is(undefined, assign1); update({ typed: 'tsn dif', cursor: { start: 7, end: 7 } }); test.is( 'VVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn dif', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsn dif ', cursor: { start: 8, end: 8 } }); test.is( 'VVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn dif', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsn dif x', cursor: { start: 9, end: 9 } }); test.is( 'VVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tsn dif', requ.commandAssignment.value.name); test.is('x', assign1.arg.text); test.is('x', assign1.value); update({ typed: 'tsn ext', cursor: { start: 7, end: 7 } }); test.is( 'VVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn ext', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsn exte', cursor: { start: 8, end: 8 } }); test.is( 'VVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn exte', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsn exten', cursor: { start: 9, end: 9 } }); test.is( 'VVVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn exten', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'tsn extend', cursor: { start: 10, end: 10 } }); test.is( 'VVVVVVVVVV', statuses); test.is(Status.ERROR, status); test.is('tsn extend', requ.commandAssignment.value.name); test.is('', assign1.arg.text); test.is(undefined, assign1.value); update({ typed: 'ts ', cursor: { start: 3, end: 3 } }); test.is( 'EEV', statuses); test.is(Status.ERROR, status); test.is('ts', requ.commandAssignment.arg.text); test.is(undefined, assign1); }; // From Bug 664203 exports.testDeeplyNested = function() { update({ typed: 'tsn deep down nested cmd', cursor: { start: 24, end: 24 } }); test.is( 'VVVVVVVVVVVVVVVVVVVVVVVV', statuses); test.is(Status.VALID, status); test.is('tsn deep down nested cmd', requ.commandAssignment.value.name); test.is(undefined, assign1); update({ typed: 'tsn deep down nested', cursor: { start: 20, end: 20 } }); test.is( 'IIIVIIIIVIIIIVIIIIII', statuses); test.is(Status.ERROR, status); test.is('tsn deep down nested', requ.commandAssignment.value.name); test.is(undefined, assign1); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/commands', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/util', 'gcli/types/selection', 'gcli/types/basic', 'gcli/types'], function(require, exports, module) { var commands = exports; var canon = require('gcli/canon'); var util = require('gcli/util'); var SelectionType = require('gcli/types/selection').SelectionType; var DeferredType = require('gcli/types/basic').DeferredType; var types = require('gcli/types'); /** * Registration and de-registration. */ commands.setup = function() { // setup/shutdown need to register/unregister types, however that means we // need to re-initialize commands.option1 and commands.option2 with the // actual types commands.option1.type = types.getType('string'); commands.option2.type = types.getType('number'); types.registerType(commands.optionType); types.registerType(commands.optionValue); canon.addCommand(commands.tsv); canon.addCommand(commands.tsr); canon.addCommand(commands.tse); canon.addCommand(commands.tsj); canon.addCommand(commands.tsb); canon.addCommand(commands.tss); canon.addCommand(commands.tsu); canon.addCommand(commands.tsn); canon.addCommand(commands.tsnDif); canon.addCommand(commands.tsnExt); canon.addCommand(commands.tsnExte); canon.addCommand(commands.tsnExten); canon.addCommand(commands.tsnExtend); canon.addCommand(commands.tsnDeep); canon.addCommand(commands.tsnDeepDown); canon.addCommand(commands.tsnDeepDownNested); canon.addCommand(commands.tsnDeepDownNestedCmd); canon.addCommand(commands.tselarr); canon.addCommand(commands.tsm); canon.addCommand(commands.tsg); }; commands.shutdown = function() { canon.removeCommand(commands.tsv); canon.removeCommand(commands.tsr); canon.removeCommand(commands.tse); canon.removeCommand(commands.tsj); canon.removeCommand(commands.tsb); canon.removeCommand(commands.tss); canon.removeCommand(commands.tsu); canon.removeCommand(commands.tsn); canon.removeCommand(commands.tsnDif); canon.removeCommand(commands.tsnExt); canon.removeCommand(commands.tsnExte); canon.removeCommand(commands.tsnExten); canon.removeCommand(commands.tsnExtend); canon.removeCommand(commands.tsnDeep); canon.removeCommand(commands.tsnDeepDown); canon.removeCommand(commands.tsnDeepDownNested); canon.removeCommand(commands.tsnDeepDownNestedCmd); canon.removeCommand(commands.tselarr); canon.removeCommand(commands.tsm); canon.removeCommand(commands.tsg); types.deregisterType(commands.optionType); types.deregisterType(commands.optionValue); }; commands.option1 = { type: types.getType('string') }; commands.option2 = { type: types.getType('number') }; var lastOption = undefined; commands.optionType = new SelectionType({ name: 'optionType', lookup: [ { name: 'option1', value: commands.option1 }, { name: 'option2', value: commands.option2 } ], noMatch: function() { lastOption = undefined; }, stringify: function(option) { lastOption = option; return SelectionType.prototype.stringify.call(this, option); }, parse: function(arg) { var conversion = SelectionType.prototype.parse.call(this, arg); lastOption = conversion.value; return conversion; } }); commands.optionValue = new DeferredType({ name: 'optionValue', defer: function() { if (lastOption && lastOption.type) { return lastOption.type; } else { return types.getType('blank'); } } }); commands.onCommandExec = util.createEvent('commands.onCommandExec'); function createExec(name) { return function(args, context) { var data = { command: commands[name], args: args, context: context }; commands.onCommandExec(data); return data; }; } commands.tsv = { name: 'tsv', params: [ { name: 'optionType', type: 'optionType' }, { name: 'optionValue', type: 'optionValue' } ], exec: createExec('tsv') }; commands.tsr = { name: 'tsr', params: [ { name: 'text', type: 'string' } ], exec: createExec('tsr') }; commands.tse = { name: 'tse', params: [ { name: 'node', type: 'node' } ], exec: createExec('tse') }; commands.tsj = { name: 'tsj', params: [ { name: 'javascript', type: 'javascript' } ], exec: createExec('tsj') }; commands.tsb = { name: 'tsb', params: [ { name: 'toggle', type: 'boolean' } ], exec: createExec('tsb') }; commands.tss = { name: 'tss', exec: createExec('tss') }; commands.tsu = { name: 'tsu', params: [ { name: 'num', type: { name: 'number', max: 10, min: -5, step: 3 } } ], exec: createExec('tsu') }; commands.tsn = { name: 'tsn' }; commands.tsnDif = { name: 'tsn dif', params: [ { name: 'text', type: 'string' } ], exec: createExec('tsnDif') }; commands.tsnExt = { name: 'tsn ext', params: [ { name: 'text', type: 'string' } ], exec: createExec('tsnExt') }; commands.tsnExte = { name: 'tsn exte', params: [ { name: 'text', type: 'string' } ], exec: createExec('') }; commands.tsnExten = { name: 'tsn exten', params: [ { name: 'text', type: 'string' } ], exec: createExec('tsnExte') }; commands.tsnExtend = { name: 'tsn extend', params: [ { name: 'text', type: 'string' } ], exec: createExec('tsnExtend') }; commands.tsnDeep = { name: 'tsn deep', }; commands.tsnDeepDown = { name: 'tsn deep down', }; commands.tsnDeepDownNested = { name: 'tsn deep down nested', }; commands.tsnDeepDownNestedCmd = { name: 'tsn deep down nested cmd', exec: createExec('tsnDeepDownNestedCmd') }; commands.tselarr = { name: 'tselarr', params: [ { name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } }, { name: 'arr', type: { name: 'array', subtype: 'string' } }, ], exec: createExec('tselarr') }; commands.tsm = { name: 'tsm', description: 'a 3-param test selection|string|number', params: [ { name: 'abc', type: { name: 'selection', data: [ 'a', 'b', 'c' ] } }, { name: 'txt', type: 'string' }, { name: 'num', type: { name: 'number', max: 42, min: 0 } }, ], exec: createExec('tsm') }; commands.tsg = { name: 'tsg', description: 'a param group test', params: [ { name: 'solo', type: { name: 'selection', data: [ 'aaa', 'bbb', 'ccc' ] } }, { group: 'First', params: [ { name: 'txt1', type: 'string', defaultValue: null }, { name: 'bool', type: 'boolean' } ] }, { group: 'Second', params: [ { name: 'txt2', type: 'string', defaultValue: 'd' }, { name: 'num', type: { name: 'number', min: 40 }, defaultValue: 42 } ] } ], exec: createExec('tsg') }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('test/assert', ['require', 'exports', 'module' ], function(require, exports, module) { exports.ok = ok; exports.is = is; exports.log = info; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testCompletion', ['require', 'exports', 'module' , 'test/assert', 'gclitest/commands'], function(require, exports, module) { var test = require('test/assert'); var commands = require('gclitest/commands'); exports.setup = function() { commands.setup(); }; exports.shutdown = function() { commands.shutdown(); }; function type(typed, tests, options) { var inputter = options.display.inputter; var completer = options.display.completer; inputter.setInput(typed); if (tests.cursor) { inputter.setCursor({ start: tests.cursor, end: tests.cursor }); } if (tests.emptyParameters == null) { tests.emptyParameters = []; } var realParams = completer.emptyParameters; test.is(tests.emptyParameters.length, realParams.length, 'emptyParameters.length for \'' + typed + '\''); if (realParams.length === tests.emptyParameters.length) { for (var i = 0; i < realParams.length; i++) { test.is(tests.emptyParameters[i], realParams[i].replace(/\u00a0/g, ' '), 'emptyParameters[' + i + '] for \'' + typed + '\''); } } if (tests.directTabText) { test.is(tests.directTabText, completer.directTabText, 'directTabText for \'' + typed + '\''); } else { test.is('', completer.directTabText, 'directTabText for \'' + typed + '\''); } if (tests.arrowTabText) { test.is(' \u00a0\u21E5 ' + tests.arrowTabText, completer.arrowTabText, 'arrowTabText for \'' + typed + '\''); } else { test.is('', completer.arrowTabText, 'arrowTabText for \'' + typed + '\''); } } exports.testActivate = function(options) { if (!options.display) { test.log('No display. Skipping activate tests'); return; } type('', { }, options); type(' ', { }, options); type('tsr', { emptyParameters: [ ' ' ] }, options); type('tsr ', { emptyParameters: [ '' ] }, options); type('tsr b', { }, options); type('tsb', { emptyParameters: [ ' [toggle]' ] }, options); type('tsm', { emptyParameters: [ ' ', ' ', ' ' ] }, options); type('tsm ', { emptyParameters: [ ' ', ' ' ], directTabText: 'a' }, options); type('tsm a', { emptyParameters: [ ' ', ' ' ] }, options); type('tsm a ', { emptyParameters: [ '', ' ' ] }, options); type('tsm a ', { emptyParameters: [ '', ' ' ] }, options); type('tsm a d', { emptyParameters: [ ' ' ] }, options); type('tsm a "d d"', { emptyParameters: [ ' ' ] }, options); type('tsm a "d ', { emptyParameters: [ ' ' ] }, options); type('tsm a "d d" ', { emptyParameters: [ '' ] }, options); type('tsm a "d d ', { emptyParameters: [ ' ' ] }, options); type('tsm d r', { emptyParameters: [ ' ' ] }, options); type('tsm a d ', { emptyParameters: [ '' ] }, options); type('tsm a d 4', { }, options); type('tsg', { emptyParameters: [ ' ' ] }, options); type('tsg ', { directTabText: 'aaa' }, options); type('tsg a', { directTabText: 'aa' }, options); type('tsg b', { directTabText: 'bb' }, options); type('tsg d', { }, options); type('tsg aa', { directTabText: 'a' }, options); type('tsg aaa', { }, options); type('tsg aaa ', { }, options); type('tsg aaa d', { }, options); type('tsg aaa dddddd', { }, options); type('tsg aaa dddddd ', { }, options); type('tsg aaa "d', { }, options); type('tsg aaa "d d', { }, options); type('tsg aaa "d d"', { }, options); type('tsn ex ', { }, options); type('selarr', { arrowTabText: 'tselarr' }, options); type('tselar 1', { }, options); type('tselar 1', { cursor: 7 }, options); type('tselar 1', { cursor: 6, arrowTabText: 'tselarr' }, options); type('tselar 1', { cursor: 5, arrowTabText: 'tselarr' }, options); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testExec', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/canon', 'gclitest/commands', 'gcli/types/node', 'test/assert'], function(require, exports, module) { var Requisition = require('gcli/cli').Requisition; var canon = require('gcli/canon'); var commands = require('gclitest/commands'); var nodetype = require('gcli/types/node'); var test = require('test/assert'); var actualExec; var actualOutput; var hideExec = false; exports.setup = function() { commands.setup(); commands.onCommandExec.add(commandExeced); canon.commandOutputManager.onOutput.add(commandOutputed); }; exports.shutdown = function() { commands.shutdown(); commands.onCommandExec.remove(commandExeced); canon.commandOutputManager.onOutput.remove(commandOutputed); }; function commandExeced(ev) { actualExec = ev; } function commandOutputed(ev) { actualOutput = ev.output; } function exec(command, expectedArgs) { var environment = {}; var requisition = new Requisition(environment); var outputObject = requisition.exec({ typed: command, hidden: hideExec }); test.is(command.indexOf(actualExec.command.name), 0, 'Command name: ' + command); test.is(command, outputObject.typed, 'outputObject.command for: ' + command); test.ok(outputObject.completed, 'outputObject.completed false for: ' + command); if (expectedArgs == null) { test.ok(false, 'expectedArgs == null for ' + command); return; } if (actualExec.args == null) { test.ok(false, 'actualExec.args == null for ' + command); return; } test.is(Object.keys(expectedArgs).length, Object.keys(actualExec.args).length, 'Arg count: ' + command); Object.keys(expectedArgs).forEach(function(arg) { var expectedArg = expectedArgs[arg]; var actualArg = actualExec.args[arg]; if (Array.isArray(expectedArg)) { if (!Array.isArray(actualArg)) { test.ok(false, 'actual is not an array. ' + command + '/' + arg); return; } test.is(expectedArg.length, actualArg.length, 'Array length: ' + command + '/' + arg); for (var i = 0; i < expectedArg.length; i++) { test.is(expectedArg[i], actualArg[i], 'Member: "' + command + '/' + arg + '/' + i); } } else { test.is(expectedArg, actualArg, 'Command: "' + command + '" arg: ' + arg); } }); test.is(environment, actualExec.context.environment, 'Environment'); if (!hideExec) { test.is(false, actualOutput.error, 'output error is false'); test.is(command, actualOutput.typed, 'command is typed'); test.ok(typeof actualOutput.canonical === 'string', 'canonical exists'); test.is(actualExec.args, actualOutput.args, 'actualExec.args is actualOutput.args'); } } exports.testExec = function(options) { hideExec = options.hideExec; exec('tss', {}); // Bug 707008 - GCLI deferred types don't work properly exec('tsv option1 10', { optionType: commands.option1, optionValue: '10' }); exec('tsv option2 10', { optionType: commands.option2, optionValue: 10 }); exec('tsr fred', { text: 'fred' }); exec('tsr fred bloggs', { text: 'fred bloggs' }); exec('tsr "fred bloggs"', { text: 'fred bloggs' }); exec('tsb', { toggle: false }); exec('tsb --toggle', { toggle: true }); exec('tsu 10', { num: 10 }); exec('tsu --num 10', { num: 10 }); // Bug 704829 - Enable GCLI Javascript parameters // The answer to this should be 2 exec('tsj { 1 + 1 }', { javascript: '1 + 1' }); var origDoc = nodetype.getDocument(); nodetype.setDocument(mockDoc); exec('tse :root', { node: mockBody }); nodetype.setDocument(origDoc); exec('tsn dif fred', { text: 'fred' }); exec('tsn exten fred', { text: 'fred' }); exec('tsn extend fred', { text: 'fred' }); exec('tselarr 1', { num: '1', arr: [ ] }); exec('tselarr 1 a', { num: '1', arr: [ 'a' ] }); exec('tselarr 1 a b', { num: '1', arr: [ 'a', 'b' ] }); exec('tsm a 10 10', { abc: 'a', txt: '10', num: 10 }); // Bug 707009 - GCLI doesn't always fill in default parameters properly exec('tsg aaa', { solo: 'aaa', txt1: null, bool: false, txt2: 'd', num: 42 }); }; var mockBody = { style: {} }; var mockDoc = { querySelectorAll: function(css) { if (css === ':root') { return { length: 1, item: function(i) { return mockBody; } }; } throw new Error('mockDoc.querySelectorAll(\'' + css + '\') error'); } }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testHistory', ['require', 'exports', 'module' , 'test/assert', 'gcli/history'], function(require, exports, module) { var test = require('test/assert'); var History = require('gcli/history').History; exports.setup = function() { }; exports.shutdown = function() { }; exports.testSimpleHistory = function () { var history = new History({}); history.add('foo'); history.add('bar'); test.is('bar', history.backward()); test.is('foo', history.backward()); // Adding to the history again moves us back to the start of the history. history.add('quux'); test.is('quux', history.backward()); test.is('bar', history.backward()); test.is('foo', history.backward()); }; exports.testBackwardsPastIndex = function () { var history = new History({}); history.add('foo'); history.add('bar'); test.is('bar', history.backward()); test.is('foo', history.backward()); // Moving backwards past recorded history just keeps giving you the last // item. test.is('foo', history.backward()); }; exports.testForwardsPastIndex = function () { var history = new History({}); history.add('foo'); history.add('bar'); test.is('bar', history.backward()); test.is('foo', history.backward()); // Going forward through the history again. test.is('bar', history.forward()); // 'Present' time. test.is('', history.forward()); // Going to the 'future' just keeps giving us the empty string. test.is('', history.forward()); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testJs', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/types', 'gcli/types/javascript', 'gcli/canon', 'test/assert'], function(require, exports, module) { var Requisition = require('gcli/cli').Requisition; var Status = require('gcli/types').Status; var javascript = require('gcli/types/javascript'); var canon = require('gcli/canon'); var test = require('test/assert'); var debug = false; var requ; var assign; var status; var statuses; var tempWindow; exports.setup = function(options) { tempWindow = javascript.getGlobalObject(); javascript.setGlobalObject(options.window); Object.defineProperty(options.window, 'donteval', { get: function() { test.ok(false, 'donteval should not be used'); return { cant: '', touch: '', 'this': '' }; }, enumerable: true, configurable : true }); }; exports.shutdown = function(options) { delete options.window.donteval; javascript.setGlobalObject(tempWindow); tempWindow = undefined; }; function input(typed) { if (!requ) { requ = new Requisition(); } var cursor = { start: typed.length, end: typed.length }; requ.update(typed); if (debug) { console.log('####### TEST: typed="' + typed + '" cur=' + cursor.start + ' cli=', requ); } status = requ.getStatus(); statuses = requ.getInputStatusMarkup(cursor.start).map(function(s) { return Array(s.string.length + 1).join(s.status.toString()[0]); }).join(''); if (requ.commandAssignment.value) { assign = requ.getAssignment(0); } else { assign = undefined; } } function predictionsHas(name) { return assign.getPredictions().some(function(prediction) { return name === prediction.name; }, this); } 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(', ')); } } } exports.testBasic = function(options) { if (!canon.getCommand('{')) { test.log('Skipping exec tests because { is not registered'); return; } input('{'); check('V', Status.ERROR, undefined); input('{ '); check('VV', Status.ERROR, undefined); input('{ w'); check('VVI', Status.ERROR, 'w', 'window'); input('{ windo'); check('VVIIIII', Status.ERROR, 'windo', 'window'); input('{ window'); check('VVVVVVVV', Status.VALID, 'window'); 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 options.window, '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); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testKeyboard', ['require', 'exports', 'module' , 'gcli/cli', 'gcli/canon', 'gclitest/commands', 'gcli/types/javascript', 'test/assert'], function(require, exports, module) { var Requisition = require('gcli/cli').Requisition; var canon = require('gcli/canon'); var commands = require('gclitest/commands'); var javascript = require('gcli/types/javascript'); var test = require('test/assert'); var tempWindow; var inputter; exports.setup = function(options) { tempWindow = javascript.getGlobalObject(); javascript.setGlobalObject(options.window); if (options.display) { inputter = options.display.inputter; } commands.setup(); }; exports.shutdown = function(options) { commands.shutdown(); inputter = undefined; javascript.setGlobalObject(tempWindow); tempWindow = undefined; }; var COMPLETES_TO = 'complete'; var KEY_UPS_TO = 'keyup'; var KEY_DOWNS_TO = 'keydown'; function check(initial, action, after, choice, cursor, expectedCursor) { var requisition; if (inputter) { requisition = inputter.requisition; inputter.setInput(initial); } else { requisition = new Requisition(); requisition.update(initial); } if (cursor == null) { cursor = initial.length; } var assignment = requisition.getAssignmentAt(cursor); switch (action) { case COMPLETES_TO: requisition.complete({ start: cursor, end: cursor }, choice); break; case KEY_UPS_TO: assignment.increment(); break; case KEY_DOWNS_TO: assignment.decrement(); break; } test.is(after, requisition.toString(), initial + ' + ' + action + ' -> ' + after); if (expectedCursor != null) { if (inputter) { test.is(expectedCursor, inputter.getInputState().cursor.start, 'Ending cursor position for \'' + initial + '\''); } } } exports.testComplete = function(options) { if (!inputter) { test.log('Missing display, reduced checks'); } check('tsela', COMPLETES_TO, 'tselarr ', 0); check('tsn di', COMPLETES_TO, 'tsn dif ', 0); check('tsg a', COMPLETES_TO, 'tsg aaa ', 0); check('tsn e', COMPLETES_TO, 'tsn extend ', -5); check('tsn e', COMPLETES_TO, 'tsn ext ', -4); check('tsn e', COMPLETES_TO, 'tsn exte ', -3); check('tsn e', COMPLETES_TO, 'tsn exten ', -2); check('tsn e', COMPLETES_TO, 'tsn extend ', -1); check('tsn e', COMPLETES_TO, 'tsn ext ', 0); check('tsn e', COMPLETES_TO, 'tsn exte ', 1); check('tsn e', COMPLETES_TO, 'tsn exten ', 2); check('tsn e', COMPLETES_TO, 'tsn extend ', 3); check('tsn e', COMPLETES_TO, 'tsn ext ', 4); check('tsn e', COMPLETES_TO, 'tsn exte ', 5); check('tsn e', COMPLETES_TO, 'tsn exten ', 6); check('tsn e', COMPLETES_TO, 'tsn extend ', 7); check('tsn e', COMPLETES_TO, 'tsn ext ', 8); if (!canon.getCommand('{')) { test.log('Skipping exec tests because { is not registered'); } else { check('{ wind', COMPLETES_TO, '{ window', 0); check('{ window.docum', COMPLETES_TO, '{ window.document', 0); // Bug 717228: This fails under node if (!options.isNode) { check('{ window.document.titl', COMPLETES_TO, '{ window.document.title ', 0); } else { test.log('Running under Node. Skipping tests due to bug 717228.'); } } }; exports.testInternalComplete = function(options) { // Bug 664377 // check('tsela 1', COMPLETES_TO, 'tselarr 1', 0, 3, 8); }; exports.testIncrDecr = function() { check('tsu -70', KEY_UPS_TO, 'tsu -5'); check('tsu -7', KEY_UPS_TO, 'tsu -5'); check('tsu -6', KEY_UPS_TO, 'tsu -5'); check('tsu -5', KEY_UPS_TO, 'tsu -3'); check('tsu -4', KEY_UPS_TO, 'tsu -3'); check('tsu -3', KEY_UPS_TO, 'tsu 0'); check('tsu -2', KEY_UPS_TO, 'tsu 0'); check('tsu -1', KEY_UPS_TO, 'tsu 0'); check('tsu 0', KEY_UPS_TO, 'tsu 3'); check('tsu 1', KEY_UPS_TO, 'tsu 3'); check('tsu 2', KEY_UPS_TO, 'tsu 3'); check('tsu 3', KEY_UPS_TO, 'tsu 6'); check('tsu 4', KEY_UPS_TO, 'tsu 6'); check('tsu 5', KEY_UPS_TO, 'tsu 6'); check('tsu 6', KEY_UPS_TO, 'tsu 9'); check('tsu 7', KEY_UPS_TO, 'tsu 9'); check('tsu 8', KEY_UPS_TO, 'tsu 9'); check('tsu 9', KEY_UPS_TO, 'tsu 10'); check('tsu 10', KEY_UPS_TO, 'tsu 10'); check('tsu 100', KEY_UPS_TO, 'tsu -5'); check('tsu -70', KEY_DOWNS_TO, 'tsu 10'); check('tsu -7', KEY_DOWNS_TO, 'tsu 10'); check('tsu -6', KEY_DOWNS_TO, 'tsu 10'); check('tsu -5', KEY_DOWNS_TO, 'tsu -5'); check('tsu -4', KEY_DOWNS_TO, 'tsu -5'); check('tsu -3', KEY_DOWNS_TO, 'tsu -5'); check('tsu -2', KEY_DOWNS_TO, 'tsu -3'); check('tsu -1', KEY_DOWNS_TO, 'tsu -3'); check('tsu 0', KEY_DOWNS_TO, 'tsu -3'); check('tsu 1', KEY_DOWNS_TO, 'tsu 0'); check('tsu 2', KEY_DOWNS_TO, 'tsu 0'); check('tsu 3', KEY_DOWNS_TO, 'tsu 0'); check('tsu 4', KEY_DOWNS_TO, 'tsu 3'); check('tsu 5', KEY_DOWNS_TO, 'tsu 3'); check('tsu 6', KEY_DOWNS_TO, 'tsu 3'); check('tsu 7', KEY_DOWNS_TO, 'tsu 6'); check('tsu 8', KEY_DOWNS_TO, 'tsu 6'); check('tsu 9', KEY_DOWNS_TO, 'tsu 6'); check('tsu 10', KEY_DOWNS_TO, 'tsu 9'); check('tsu 100', KEY_DOWNS_TO, 'tsu 10'); // Bug 707007 - GCLI increment and decrement operations cycle through // selection options in the wrong order check('tselarr 1', KEY_DOWNS_TO, 'tselarr 2'); check('tselarr 2', KEY_DOWNS_TO, 'tselarr 3'); check('tselarr 3', KEY_DOWNS_TO, 'tselarr 1'); check('tselarr 3', KEY_UPS_TO, 'tselarr 2'); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testRequire', ['require', 'exports', 'module' , 'test/assert', 'gclitest/requirable'], function(require, exports, module) { var test = require('test/assert'); exports.testWorking = function() { // There are lots of requirement tests that we could be doing here // The fact that we can get anything at all working is a testament to // require doing what it should - we don't need to test the var requireable = require('gclitest/requirable'); test.is('thing1', requireable.thing1); test.is(2, requireable.thing2); test.ok(requireable.thing3 === undefined); }; exports.testDomains = function() { var requireable = require('gclitest/requirable'); test.ok(requireable.status === undefined); requireable.setStatus(null); test.is(null, requireable.getStatus()); test.ok(requireable.status === undefined); requireable.setStatus('42'); test.is('42', requireable.getStatus()); test.ok(requireable.status === undefined); if (define.Domain) { var domain = new define.Domain(); var requireable2 = domain.require('gclitest/requirable'); test.is(undefined, requireable2.status); test.is('initial', requireable2.getStatus()); requireable2.setStatus(999); test.is(999, requireable2.getStatus()); test.is(undefined, requireable2.status); test.is('42', requireable.getStatus()); test.is(undefined, requireable.status); } }; exports.testLeakage = function() { var requireable = require('gclitest/requirable'); test.ok(requireable.setup === undefined); test.ok(requireable.shutdown === undefined); test.ok(requireable.testWorking === undefined); }; exports.testMultiImport = function() { var r1 = require('gclitest/requirable'); var r2 = require('gclitest/requirable'); test.is(r1, r2); }; exports.testUncompilable = function() { // This test is commented out because it breaks the RequireJS module // loader and because it causes console output and because testing failure // cases such as this is something of a luxury // It's not totally clear how a module loader should perform with unusable // modules, however at least it should go into a flat spin ... // GCLI mini_require reports an error as it should /* if (define.Domain) { try { var unrequireable = require('gclitest/unrequirable'); t.fail(); } catch (ex) { console.error(ex); } } */ }; exports.testRecursive = function() { // See Bug 658583 /* var recurse = require('gclitest/recurse'); */ }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/requirable', ['require', 'exports', 'module' ], function(require, exports, module) { exports.thing1 = 'thing1'; exports.thing2 = 2; var status = 'initial'; exports.setStatus = function(aStatus) { status = aStatus; }; exports.getStatus = function() { return status; }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testResource', ['require', 'exports', 'module' , 'gcli/types/resource', 'gcli/types', 'test/assert'], function(require, exports, module) { var resource = require('gcli/types/resource'); var types = require('gcli/types'); var Status = require('gcli/types').Status; var test = require('test/assert'); var tempDocument; exports.setup = function(options) { tempDocument = resource.getDocument(); resource.setDocument(options.window.document); }; exports.shutdown = function(options) { resource.setDocument(tempDocument); tempDocument = undefined; }; exports.testPredictions = function(options) { if (options.window.isFake) { test.log('Skipping resource tests: options.window.isFake = true'); return; } var resource1 = types.getType('resource'); var predictions1 = resource1.parseString('').getPredictions(); test.ok(predictions1.length > 1, 'have resources'); predictions1.forEach(function(prediction) { checkPrediction(resource1, prediction); }); var resource2 = types.getType({ name: 'resource', include: 'text/javascript' }); var predictions2 = resource2.parseString('').getPredictions(); test.ok(predictions2.length > 1, 'have resources'); predictions2.forEach(function(prediction) { checkPrediction(resource2, prediction); }); var resource3 = types.getType({ name: 'resource', include: 'text/css' }); var predictions3 = resource3.parseString('').getPredictions(); // jsdom fails to support digging into stylesheets if (!options.isNode) { test.ok(predictions3.length >= 1, 'have resources'); } else { test.log('Running under Node. ' + 'Skipping checks due to jsdom document.stylsheets support.'); } predictions3.forEach(function(prediction) { checkPrediction(resource3, prediction); }); var resource4 = types.getType({ name: 'resource' }); var predictions4 = resource4.parseString('').getPredictions(); test.is(predictions1.length, predictions4.length, 'type spec'); // Bug 734045 // test.is(predictions2.length + predictions3.length, predictions4.length, 'split'); }; function checkPrediction(res, prediction) { var name = prediction.name; var value = prediction.value; var conversion = res.parseString(name); test.is(conversion.getStatus(), Status.VALID, 'status VALID for ' + name); test.is(conversion.value, value, 'value for ' + name); var strung = res.stringify(value); test.is(strung, name, 'stringify for ' + name); test.is(typeof value.loadContents, 'function', 'resource for ' + name); test.is(typeof value.element, 'object', 'resource for ' + name); } }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testScratchpad', ['require', 'exports', 'module' , 'test/assert'], function(require, exports, module) { var test = require('test/assert'); var origScratchpad; exports.setup = function(options) { if (options.display) { origScratchpad = options.display.inputter.scratchpad; options.display.inputter.scratchpad = stubScratchpad; } }; exports.shutdown = function(options) { if (options.display) { options.display.inputter.scratchpad = origScratchpad; } }; var stubScratchpad = { shouldActivate: function(ev) { return true; }, activatedCount: 0, linkText: 'scratchpad.linkText' }; stubScratchpad.activate = function(value) { stubScratchpad.activatedCount++; return true; }; exports.testActivate = function(options) { if (!options.display) { test.log('No display. Skipping scratchpad tests'); return; } var ev = {}; stubScratchpad.activatedCount = 0; options.display.inputter.onKeyUp(ev); test.is(1, stubScratchpad.activatedCount, 'scratchpad is activated'); }; }); /* * Copyright (c) 2009 Panagiotis Astithas * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ define('gclitest/testSpell', ['require', 'exports', 'module' , 'test/assert', 'gcli/types/spell'], function(require, exports, module) { var test = require('test/assert'); var Speller = require('gcli/types/spell').Speller; exports.setup = function() { }; exports.shutdown = function() { }; exports.testSimple = function(options) { var speller = new Speller(); speller.train(Object.keys(options.window)); test.is(speller.correct('document'), 'document'); test.is(speller.correct('documen'), 'document'); test.is(speller.correct('ocument'), 'document'); test.is(speller.correct('odcument'), 'document'); test.is(speller.correct('========='), null); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testSplit', ['require', 'exports', 'module' , 'test/assert', 'gclitest/commands', 'gcli/cli'], function(require, exports, module) { var test = require('test/assert'); var commands = require('gclitest/commands'); var Requisition = require('gcli/cli').Requisition; exports.setup = function() { commands.setup(); }; exports.shutdown = function() { commands.shutdown(); }; exports.testSimple = function() { var args; var requ = new Requisition(); args = requ._tokenize('s'); requ._split(args); test.is(0, args.length); test.is('s', requ.commandAssignment.arg.text); }; exports.testFlatCommand = function() { var args; var requ = new Requisition(); args = requ._tokenize('tsv'); requ._split(args); test.is(0, args.length); test.is('tsv', requ.commandAssignment.value.name); args = requ._tokenize('tsv a b'); requ._split(args); test.is('tsv', requ.commandAssignment.value.name); test.is(2, args.length); test.is('a', args[0].text); test.is('b', args[1].text); }; exports.testJavascript = function() { var args; var requ = new Requisition(); args = requ._tokenize('{'); requ._split(args); test.is(1, args.length); test.is('', args[0].text); test.is('', requ.commandAssignment.arg.text); test.is('{', requ.commandAssignment.value.name); }; // BUG 663081 - add tests for sub commands }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testTokenize', ['require', 'exports', 'module' , 'test/assert', 'gcli/cli', 'gcli/argument'], function(require, exports, module) { var test = require('test/assert'); var Requisition = require('gcli/cli').Requisition; var Argument = require('gcli/argument').Argument; var ScriptArgument = require('gcli/argument').ScriptArgument; exports.testBlanks = 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); args = requ._tokenize(' '); test.is(1, args.length); test.is('', args[0].text); test.is(' ', args[0].prefix); test.is('', args[0].suffix); }; 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.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); }; 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); }; 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); }; 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); }; 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); }; 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); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testTooltip', ['require', 'exports', 'module' , 'test/assert', 'gclitest/commands'], function(require, exports, module) { var test = require('test/assert'); var commands = require('gclitest/commands'); exports.setup = function() { commands.setup(); }; exports.shutdown = function() { commands.shutdown(); }; function type(typed, tests, options) { var inputter = options.display.inputter; var tooltip = options.display.tooltip; inputter.setInput(typed); if (tests.cursor) { inputter.setCursor({ start: tests.cursor, end: tests.cursor }); } if (!options.isNode) { if (tests.important) { test.ok(tooltip.field.isImportant, 'Important for ' + typed); } else { test.ok(!tooltip.field.isImportant, 'Not important for ' + typed); } if (tests.options) { var names = tooltip.field.menu.items.map(function(item) { return item.name.textContent ? item.name.textContent : item.name; }); test.is(tests.options.join('|'), names.join('|'), 'Options for ' + typed); } if (tests.error) { test.is(tests.error, tooltip.errorEle.textContent, 'Error for ' + typed); } else { test.is('', tooltip.errorEle.textContent, 'No error for ' + typed); } } } exports.testActivate = function(options) { if (!options.display) { test.log('No display. Skipping activate tests'); return; } if (options.isNode) { test.log('Running under Node. Reduced checks due to JSDom.textContent'); } type(' ', { }, options); type('tsb ', { important: true, options: [ 'false', 'true' ] }, options); type('tsb t', { important: true, options: [ 'true' ] }, options); type('tsb tt', { important: true, options: [ ], error: 'Can\'t use \'tt\'.' }, options); type('asdf', { important: false, options: [ ], error: 'Can\'t use \'asdf\'.' }, options); type('', { }, options); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testTypes', ['require', 'exports', 'module' , 'test/assert', 'gcli/types'], function(require, exports, module) { var test = require('test/assert'); var types = require('gcli/types'); exports.setup = function() { }; exports.shutdown = function() { }; exports.testDefault = function(options) { if (options.isNode) { test.log('Running under Node. ' + 'Skipping tests due to issues with resource type.'); return; } types.getTypeNames().forEach(function(name) { if (name === 'selection') { name = { name: 'selection', data: [ 'a', 'b' ] }; } if (name === 'deferred') { name = { name: 'deferred', defer: function() { return types.getType('string'); } }; } if (name === 'array') { name = { name: 'array', subtype: 'string' }; } var type = types.getType(name); if (type.name !== 'boolean' && type.name !== 'array') { test.ok(type.getBlank().value === undefined, 'default defined for ' + type.name); } }); }; }); /* * Copyright 2009-2011 Mozilla Foundation and contributors * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ define('gclitest/testUtil', ['require', 'exports', 'module' , 'gcli/util', 'test/assert'], function(require, exports, module) { var util = require('gcli/util'); var test = require('test/assert'); exports.testFindCssSelector = function(options) { if (options.window.isFake) { test.log('Skipping dom.findCssSelector tests due to window.isFake'); return; } var nodes = options.window.document.querySelectorAll('*'); for (var i = 0; i < nodes.length; i++) { var selector = util.findCssSelector(nodes[i]); var matches = options.window.document.querySelectorAll(selector); test.is(matches.length, 1, 'multiple matches for ' + selector); test.is(matches[0], nodes[i], 'non-matching selector: ' + selector); } }; }); let testModuleNames = [ 'gclitest/index', 'gclitest/suite', 'test/examiner', 'gclitest/testCli', 'gclitest/commands', 'test/assert', 'gclitest/testCompletion', 'gclitest/testExec', 'gclitest/testHistory', 'gclitest/testJs', 'gclitest/testKeyboard', 'gclitest/testRequire', 'gclitest/requirable', 'gclitest/testResource', 'gclitest/testScratchpad', 'gclitest/testSpell', 'gclitest/testSplit', 'gclitest/testTokenize', 'gclitest/testTooltip', 'gclitest/testTypes', 'gclitest/testUtil', ]; // Cached so it still exists during cleanup until we need it to let localDefine; const TEST_URI = "data:text/html;charset=utf-8,gcli-web"; function test() { localDefine = define; DeveloperToolbarTest.test(TEST_URI, function(browser, tab) { var gclitest = define.globalDomain.require("gclitest/index"); gclitest.run({ display: DeveloperToolbar.display, // window: browser.getBrowser().contentWindow }); finish(); }); } registerCleanupFunction(function() { testModuleNames.forEach(function(moduleName) { delete localDefine.modules[moduleName]; delete localDefine.globalDomain.modules[moduleName]; }); localDefine = undefined; });