This commit is contained in:
Ryan VanderMeulen 2013-03-13 16:21:21 -04:00
Родитель 3733aa0609 f86723d135
Коммит fa0860f9f7
95 изменённых файлов: 13992 добавлений и 11227 удалений

Просмотреть файл

@ -15,4 +15,4 @@
#
# Note: The description below will be part of the error message shown to users.
#
Bug 825341 appears to need a clobber
Bug 847890 appears to need a clobber

Просмотреть файл

@ -1042,7 +1042,7 @@ pref("devtools.toolbox.footer.height", 250);
pref("devtools.toolbox.sidebar.width", 500);
pref("devtools.toolbox.host", "bottom");
pref("devtools.toolbox.selectedTool", "webconsole");
pref("devtools.toolbox.toolbarSpec", '["tilt toggle","scratchpad","resize toggle"]');
pref("devtools.toolbox.toolbarSpec", '["paintflashing toggle","tilt toggle","scratchpad","resize toggle"]');
pref("devtools.toolbox.sideEnabled", false);
// Enable the Inspector

Просмотреть файл

@ -15,6 +15,7 @@ Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/osfile.jsm")
Cu.import("resource:///modules/devtools/EventEmitter.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
@ -311,180 +312,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
});
}(this));
/* CmdBreak ---------------------------------------------------------------- */
(function(module) {
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
/**
* 'break' command
*/
gcli.addCommand({
name: "break",
description: gcli.lookup("breakDesc"),
manual: gcli.lookup("breakManual")
});
/**
* 'break list' command
*/
gcli.addCommand({
name: "break list",
description: gcli.lookup("breaklistDesc"),
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
if (Object.keys(breakpoints).length === 0) {
return gcli.lookup("breaklistNone");
}
let reply = gcli.lookup("breaklistIntro");
reply += "<ol>";
for each (let breakpoint in breakpoints) {
let text = gcli.lookupFormat("breaklistLineEntry",
[breakpoint.location.url,
breakpoint.location.line]);
reply += "<li>" + text + "</li>";
};
reply += "</ol>";
return reply;
}
});
/**
* 'break add' command
*/
gcli.addCommand({
name: "break add",
description: gcli.lookup("breakaddDesc"),
manual: gcli.lookup("breakaddManual")
});
/**
* 'break add line' command
*/
gcli.addCommand({
name: "break add line",
description: gcli.lookup("breakaddlineDesc"),
params: [
{
name: "file",
type: {
name: "selection",
data: function(args, context) {
let files = [];
let dbg = getPanel(context, "jsdebugger");
if (dbg) {
let sourcesView = dbg.panelWin.DebuggerView.Sources;
for (let item in sourcesView) {
files.push(item.value);
}
}
return files;
}
},
description: gcli.lookup("breakaddlineFileDesc")
},
{
name: "line",
type: { name: "number", min: 1, step: 10 },
description: gcli.lookup("breakaddlineLineDesc")
}
],
returnType: "html",
exec: function(args, context) {
args.type = "line";
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
var deferred = context.defer();
let position = { url: args.file, line: args.line };
dbg.addBreakpoint(position, function(aBreakpoint, aError) {
if (aError) {
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
return;
}
deferred.resolve(gcli.lookup("breakaddAdded"));
});
return deferred.promise;
}
});
/**
* 'break del' command
*/
gcli.addCommand({
name: "break del",
description: gcli.lookup("breakdelDesc"),
params: [
{
name: "breakid",
type: {
name: "number",
min: 0,
max: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
return dbg == null ?
null :
Object.keys(dbg.getAllBreakpoints()).length - 1;
},
},
description: gcli.lookup("breakdelBreakidDesc")
}
],
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
let id = Object.keys(breakpoints)[args.breakid];
if (!id || !(id in breakpoints)) {
return gcli.lookup("breakNotFound");
}
let deferred = context.defer();
try {
dbg.removeBreakpoint(breakpoints[id], function() {
deferred.resolve(gcli.lookup("breakdelRemoved"));
});
} catch (ex) {
// If the debugger has been closed already, don't scare the user.
deferred.resolve(gcli.lookup("breakdelRemoved"));
}
return deferred.promise;
}
});
/**
* A helper to go from a command context to a debugger panel
*/
function getPanel(context, id) {
if (context == null) {
return undefined;
}
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox == null ? undefined : toolbox.getPanel(id);
}
}(this));
/* CmdCalllog -------------------------------------------------------------- */
(function(module) {
@ -1138,206 +965,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
}
}(this));
/* CmdDbg ------------------------------------------------------------------ */
(function(module) {
/**
* 'dbg' command
*/
gcli.addCommand({
name: "dbg",
description: gcli.lookup("dbgDesc"),
manual: gcli.lookup("dbgManual")
});
/**
* 'dbg open' command
*/
gcli.addCommand({
name: "dbg open",
description: gcli.lookup("dbgOpen"),
params: [],
exec: function (args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
return gDevTools.showToolbox(target, "jsdebugger");
}
});
/**
* 'dbg close' command
*/
gcli.addCommand({
name: "dbg close",
description: gcli.lookup("dbgClose"),
params: [],
exec: function (args, context) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
return gDevTools.closeToolbox(target);
}
});
/**
* 'dbg interrupt' command
*/
gcli.addCommand({
name: "dbg interrupt",
description: gcli.lookup("dbgInterrupt"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (!thread.paused) {
thread.interrupt();
}
}
});
/**
* 'dbg continue' command
*/
gcli.addCommand({
name: "dbg continue",
description: gcli.lookup("dbgContinue"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.resume();
}
}
});
/**
* 'dbg step' command
*/
gcli.addCommand({
name: "dbg step",
description: gcli.lookup("dbgStepDesc"),
manual: gcli.lookup("dbgStepManual")
});
/**
* 'dbg step over' command
*/
gcli.addCommand({
name: "dbg step over",
description: gcli.lookup("dbgStepOverDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOver();
}
}
});
/**
* 'dbg step in' command
*/
gcli.addCommand({
name: 'dbg step in',
description: gcli.lookup("dbgStepInDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepIn();
}
}
});
/**
* 'dbg step over' command
*/
gcli.addCommand({
name: 'dbg step out',
description: gcli.lookup("dbgStepOutDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOut();
}
}
});
/**
* 'dbg list' command
*/
gcli.addCommand({
name: "dbg list",
description: gcli.lookup("dbgListSourcesDesc"),
params: [],
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
let doc = context.environment.chromeDocument;
if (!dbg) {
return gcli.lookup("debuggerClosed");
}
let sources = dbg._view.Sources.values;
let div = createXHTMLElement(doc, "div");
let ol = createXHTMLElement(doc, "ol");
sources.forEach(function(src) {
let li = createXHTMLElement(doc, "li");
li.textContent = src;
ol.appendChild(li);
});
div.appendChild(ol);
return div;
}
});
/**
* A helper to create xhtml namespaced elements
*/
function createXHTMLElement(document, tagname) {
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
}
/**
* A helper to go from a command context to a debugger panel
*/
function getPanel(context, id) {
let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox == null ? undefined : toolbox.getPanel(id);
}
}(this));
/* CmdEcho ----------------------------------------------------------------- */
(function(module) {
@ -1381,10 +1008,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
name: "export html",
description: gcli.lookup("exportHtmlDesc"),
exec: function(args, context) {
let document = context.environment.contentDocument;
let window = document.defaultView;
let page = document.documentElement.outerHTML;
window.open('data:text/plain;charset=utf8,' + encodeURIComponent(page));
let html = context.environment.document.documentElement.outerHTML;
let url = 'data:text/plain;charset=utf8,' + encodeURIComponent(html);
context.environment.window.open(url);
}
});
}(this));
@ -2061,3 +1687,122 @@ XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
}
});
}(this));
/* CmdPaintFlashing ------------------------------------------------------- */
(function(module) {
/**
* 'paintflashing' command
*/
gcli.addCommand({
name: 'paintflashing',
description: gcli.lookup('paintflashingDesc')
});
gcli.addCommand({
name: 'paintflashing on',
description: gcli.lookup('paintflashingOnDesc'),
manual: gcli.lookup('paintflashingManual'),
params: [{
group: "options",
params: [
{
type: "boolean",
name: "chrome",
get hidden() gcli.hiddenByChromePref(),
description: gcli.lookup("paintflashingChromeDesc"),
}
]
}],
exec: function(args, context) {
var window;
if (args.chrome) {
window = context.environment.chromeDocument.defaultView;
} else {
window = context.environment.contentDocument.defaultView;
}
window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).
paintFlashing = true;
onPaintFlashingChanged(context);
}
});
gcli.addCommand({
name: 'paintflashing off',
description: gcli.lookup('paintflashingOffDesc'),
manual: gcli.lookup('paintflashingManual'),
params: [{
group: "options",
params: [
{
type: "boolean",
name: "chrome",
get hidden() gcli.hiddenByChromePref(),
description: gcli.lookup("paintflashingChromeDesc"),
}
]
}],
exec: function(args, context) {
if (args.chrome) {
var window = context.environment.chromeDocument.defaultView;
} else {
var window = context.environment.contentDocument.defaultView;
}
window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils).
paintFlashing = false;
onPaintFlashingChanged(context);
}
});
gcli.addCommand({
name: 'paintflashing toggle',
hidden: true,
buttonId: "command-button-paintflashing",
buttonClass: "command-button",
state: {
isChecked: function(aTarget) {
if (aTarget.isLocalTab) {
let window = aTarget.tab.linkedBrowser.contentWindow;
let wUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
return wUtils.paintFlashing;
} else {
throw new Error("Unsupported target");
}
},
onChange: function(aTarget, aChangeHandler) {
eventEmitter.on("changed", aChangeHandler);
},
offChange: function(aTarget, aChangeHandler) {
eventEmitter.off("changed", aChangeHandler);
},
},
tooltipText: gcli.lookup("paintflashingTooltip"),
description: gcli.lookup('paintflashingOnDesc'),
manual: gcli.lookup('paintflashingManual'),
exec: function(args, context) {
var gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
var window = gBrowser.contentWindow;
var wUtils = window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
wUtils.paintFlashing = !wUtils.paintFlashing;
onPaintFlashingChanged(context);
}
});
let eventEmitter = new EventEmitter();
function onPaintFlashingChanged(context) {
var gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
var tab = gBrowser.selectedTab;
eventEmitter.emit("changed", tab);
function fireChange() {
eventEmitter.emit("changed", tab);
}
var target = TargetFactory.forTab(tab);
target.off("navigate", fireChange);
target.once("navigate", fireChange);
}
}(this));

Просмотреть файл

@ -8,6 +8,7 @@ this.EXPORTED_SYMBOLS = [ ];
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/BuiltinCommands.jsm");
Cu.import("resource:///modules/devtools/CmdDebugger.jsm");
Cu.import("resource:///modules/devtools/CmdEdit.jsm");
Cu.import("resource:///modules/devtools/CmdInspect.jsm");
Cu.import("resource:///modules/devtools/CmdResize.jsm");

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -13,13 +13,10 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
browser_cmd_addon.js \
browser_cmd_calllog.js \
browser_cmd_calllog_chrome.js \
browser_dbg_cmd_break.html \
browser_dbg_cmd_break.js \
$(browser_cmd_calllog.js disabled until bug 845831 is fixed) \
$(browser_cmd_calllog_chrome.js disabled until bug 845831 is fixed) \
browser_cmd_commands.js \
browser_cmd_cookie.js \
browser_cmd_integrate.js \
browser_cmd_jsb.js \
browser_cmd_jsb_script.jsi \
browser_cmd_pagemod_export.html \
@ -27,7 +24,7 @@ MOCHITEST_BROWSER_FILES = \
browser_cmd_pref.js \
browser_cmd_restart.js \
browser_cmd_screenshot.html \
browser_cmd_screenshot_perwindowpb.js \
browser_cmd_screenshot.js \
browser_cmd_settings.js \
browser_gcli_canon.js \
browser_gcli_cli.js \
@ -52,17 +49,7 @@ MOCHITEST_BROWSER_FILES = \
browser_gcli_util.js \
head.js \
helpers.js \
helpers_perwindowpb.js \
mockCommands.js \
$(NULL)
ifneq ($(OS_ARCH),WINNT)
MOCHITEST_BROWSER_FILES += \
browser_dbg_cmd.html \
browser_dbg_cmd.js \
$(NULL)
else
$(filter disabled-temporarily--bug-820221, browser_dbg_cmd.js)
endif
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -3,106 +3,134 @@
// Tests that the addon commands works as they should
let imported = {};
Components.utils.import("resource:///modules/devtools/BuiltinCommands.jsm", imported);
let CmdAddonFlags = (Cu.import("resource:///modules/devtools/BuiltinCommands.jsm", {})).CmdAddonFlags;
let tests = {};
function test() {
DeveloperToolbarTest.test("about:blank", [ GAT_test ]);
helpers.addTabWithToolbar("about:blank", function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}
function GAT_test() {
var GAT_ready = DeveloperToolbarTest.checkCalled(function() {
Services.obs.removeObserver(GAT_ready, "gcli_addon_commands_ready", false);
tests.gatTest = function(options) {
let deferred = Promise.defer();
// hack to reduce stack size as a result of bug 842347
let onGatReadyInterjection = function() {
executeSoon(onGatReady);
};
let onGatReady = function() {
Services.obs.removeObserver(onGatReadyInterjection, "gcli_addon_commands_ready", false);
info("gcli_addon_commands_ready notification received, running tests");
helpers.setInput('addon list dictionary');
helpers.check({
input: 'addon list dictionary',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon list extension');
helpers.check({
input: 'addon list extension',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon list locale');
helpers.check({
input: 'addon list locale',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon list plugin');
helpers.check({
input: 'addon list plugin',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon list theme');
helpers.check({
input: 'addon list theme',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon list all');
helpers.check({
input: 'addon list all',
hints: '',
markup: 'VVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon disable Test_Plug-in_1.0.0.0');
helpers.check({
input: 'addon disable Test_Plug-in_1.0.0.0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('addon disable WRONG');
helpers.check({
input: 'addon disable WRONG',
hints: '',
markup: 'VVVVVVVVVVVVVVEEEEE',
status: 'ERROR'
});
helpers.setInput('addon enable Test_Plug-in_1.0.0.0');
helpers.check({
input: 'addon enable Test_Plug-in_1.0.0.0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
command: { name: 'addon enable' },
name: { value: 'Test Plug-in', status: 'VALID' },
let auditDone = helpers.audit(options, [
{
setup: 'addon list dictionary',
check: {
input: 'addon list dictionary',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon list extension',
check: {
input: 'addon list extension',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon list locale',
check: {
input: 'addon list locale',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon list plugin',
check: {
input: 'addon list plugin',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon list theme',
check: {
input: 'addon list theme',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon list all',
check: {
input: 'addon list all',
hints: '',
markup: 'VVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon disable Test_Plug-in_1.0.0.0',
check: {
input: 'addon disable Test_Plug-in_1.0.0.0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'addon disable WRONG',
check: {
input: 'addon disable WRONG',
hints: '',
markup: 'VVVVVVVVVVVVVVEEEEE',
status: 'ERROR'
}
},
{
setup: 'addon enable Test_Plug-in_1.0.0.0',
check: {
input: 'addon enable Test_Plug-in_1.0.0.0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
command: { name: 'addon enable' },
name: { value: 'Test Plug-in', status: 'VALID' },
}
},
exec: {
completed: false
}
}
]);
auditDone.then(function() {
deferred.resolve();
});
};
DeveloperToolbarTest.exec({ completed: false });
});
Services.obs.addObserver(onGatReadyInterjection, "gcli_addon_commands_ready", false);
Services.obs.addObserver(GAT_ready, "gcli_addon_commands_ready", false);
if (imported.CmdAddonFlags.addonsLoaded) {
info("The getAllAddons command has already completed and we have missed ");
info("the notification. Let's send the gcli_addon_commands_ready ");
info("notification ourselves.");
if (CmdAddonFlags.addonsLoaded) {
info("The call to AddonManager.getAllAddons in BuiltinCommands.jsm is done.");
info("Send the gcli_addon_commands_ready notification ourselves.");
Services.obs.notifyObservers(null, "gcli_addon_commands_ready", null);
} else {
info("gcli_addon_commands_ready notification has not yet been received.");
info("Waiting for gcli_addon_commands_ready notification.");
}
}
return deferred.promise;
};

Просмотреть файл

@ -3,84 +3,112 @@
// Tests that the calllog commands works as they should
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,gcli-calllog";
let tests = {};
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testCallLogStatus, testCallLogExec ]);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}
function testCallLogStatus() {
helpers.setInput('calllog');
helpers.check({
input: 'calllog',
hints: '',
markup: 'IIIIIII',
status: 'ERROR'
});
tests.testCallLogStatus = function(options) {
return helpers.audit(options, [
{
setup: "calllog",
check: {
input: 'calllog',
hints: '',
markup: 'IIIIIII',
status: 'ERROR'
}
},
{
setup: "calllog start",
check: {
input: 'calllog start',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: "calllog stop",
check: {
input: 'calllog stop',
hints: '',
markup: 'VVVVVVVVVVVV',
status: 'VALID'
}
},
]);
};
helpers.setInput('calllog start');
helpers.check({
input: 'calllog start',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
});
tests.testCallLogExec = function(options) {
var deferred = Promise.defer();
helpers.setInput('calllog stop');
helpers.check({
input: 'calllog stop',
hints: '',
markup: 'VVVVVVVVVVVV',
status: 'VALID'
});
}
function testCallLogExec() {
DeveloperToolbarTest.exec({
typed: "calllog stop",
args: { },
outputMatch: /No call logging/,
});
let hud = null;
var onWebConsoleOpen = DeveloperToolbarTest.checkCalled(function(aSubject) {
var onWebConsoleOpen = function(subject) {
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
aSubject.QueryInterface(Ci.nsISupportsString);
hud = imported.HUDService.getHudReferenceById(aSubject.data);
ok(hud.hudId in imported.HUDService.hudReferences, "console open");
subject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
DeveloperToolbarTest.exec({
typed: "calllog stop",
args: { },
outputMatch: /Stopped call logging/,
helpers.audit(options, [
{
setup: "calllog stop",
exec: {
output: /Stopped call logging/,
}
},
{
setup: "console clear",
exec: {
output: "",
},
post: function() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
}
},
{
setup: "console close",
exec: {
output: "",
}
},
]).then(function() {
deferred.resolve();
});
DeveloperToolbarTest.exec({
typed: "console clear",
args: {},
blankOutput: true,
});
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
DeveloperToolbarTest.exec({
typed: "console close",
args: {},
blankOutput: true,
completed: false,
});
});
};
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
DeveloperToolbarTest.exec({
typed: "calllog start",
args: { },
outputMatch: /Call logging started/,
});
}
helpers.audit(options, [
{
setup: "calllog stop",
exec: {
output: /No call logging/,
}
},
{
name: "calllog start",
setup: function() {
// This test wants to be in a different event
var deferred = Promise.defer();
executeSoon(function() {
helpers.setInput(options, "calllog start");
deferred.resolve();
});
return deferred.promise;
},
exec: {
output: /Call logging started/,
},
},
]);
return deferred.promise;
};

Просмотреть файл

@ -3,111 +3,111 @@
// Tests that the calllog commands works as they should
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,cmd-calllog-chrome";
let tests = {};
function test() {
DeveloperToolbarTest.test(TEST_URI, function CLCTest(browser, tab) {
testCallLogStatus();
testCallLogExec();
});
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}
function testCallLogStatus() {
DeveloperToolbarTest.checkInputStatus({
typed: "calllog",
status: "ERROR",
emptyParameters: [ " " ]
});
tests.testCallLogStatus = function(options) {
return helpers.audit(options, [
{
setup: "calllog",
check: {
status: "ERROR",
emptyParameters: [ " " ]
}
},
{
setup: "calllog chromestop",
check: {
status: "VALID",
emptyParameters: [ " " ]
}
},
{
setup: "calllog chromestart content-variable window",
check: {
status: "VALID",
emptyParameters: [ " " ]
}
},
{
setup: "calllog chromestart javascript \"({a1: function() {this.a2()},a2: function() {}});\"",
check: {
status: "VALID",
emptyParameters: [ " " ]
}
},
]);
};
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestart content-variable window",
status: "VALID",
emptyParameters: [ " " ]
});
tests.testCallLogExec = function(options) {
let deferred = Promise.defer();
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestop",
status: "VALID",
emptyParameters: [ " " ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestart chrome-variable window",
status: "VALID",
emptyParameters: [ " " ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestop",
status: "VALID",
emptyParameters: [ " " ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestart javascript \"({a1: function() {this.a2()}," +
"a2: function() {}});\"",
status: "VALID",
emptyParameters: [ " " ]
});
DeveloperToolbarTest.checkInputStatus({
typed: "calllog chromestop",
status: "VALID",
emptyParameters: [ " " ]
});
}
function testCallLogExec() {
DeveloperToolbarTest.exec({
typed: "calllog chromestop",
args: { },
outputMatch: /No call logging/,
});
function onWebConsoleOpen(aSubject) {
function onWebConsoleOpen(subject) {
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
aSubject.QueryInterface(Ci.nsISupportsString);
let hud = imported.HUDService.getHudReferenceById(aSubject.data);
ok(hud.hudId in imported.HUDService.hudReferences, "console open");
subject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
DeveloperToolbarTest.exec({
typed: "calllog chromestop",
args: { },
outputMatch: /Stopped call logging/,
helpers.audit(options, [
{
setup: "calllog chromestop",
exec: {
output: /Stopped call logging/,
}
},
{
setup: "calllog chromestart javascript XXX",
exec: {
output: /following exception/,
}
},
{
setup: "console clear",
exec: {
output: '',
},
post: function() {
let labels = hud.jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
}
},
{
setup: "console close",
exec: {
output: '',
completed: false,
},
},
]).then(function() {
deferred.resolve();
});
DeveloperToolbarTest.exec({
typed: "calllog chromestart javascript XXX",
outputMatch: /following exception/,
});
DeveloperToolbarTest.exec({
typed: "console clear",
args: {},
blankOutput: true,
});
let labels = hud.jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
DeveloperToolbarTest.exec({
typed: "console close",
args: {},
blankOutput: true,
completed: false,
});
executeSoon(finish);
}
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
DeveloperToolbarTest.exec({
typed: "calllog chromestart javascript \"({a1: function() {this.a2()},a2: function() {}});\"",
outputMatch: /Call logging started/,
completed: false,
});
}
helpers.audit(options, [
{
setup: "calllog chromestop",
exec: {
output: /No call logging/
}
},
{
setup: "calllog chromestart javascript \"({a1: function() {this.a2()},a2: function() {}});\"",
exec: {
output: /Call logging started/,
}
},
]);
return deferred.promise;
};

Просмотреть файл

@ -3,65 +3,85 @@
// Test various GCLI commands
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
let tests = {};
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testEcho, testConsole ]);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}
function testEcho() {
DeveloperToolbarTest.exec({
typed: "echo message",
args: { message: "message" },
outputMatch: /^message$/,
});
}
tests.testEcho = function(options) {
return helpers.audit(options, [
{
setup: "echo message",
exec: {
output: "message",
}
}
]);
};
function testConsole(browser, tab) {
tests.testConsole = function(options) {
let deferred = Promise.defer();
let hud = null;
function onWebConsoleOpen(aSubject) {
let onWebConsoleOpen = function(subject) {
Services.obs.removeObserver(onWebConsoleOpen, "web-console-created");
aSubject.QueryInterface(Ci.nsISupportsString);
hud = imported.HUDService.getHudReferenceById(aSubject.data);
ok(hud.hudId in imported.HUDService.hudReferences, "console open");
subject.QueryInterface(Ci.nsISupportsString);
hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
hud.jsterm.execute("pprint(window)", onExecute);
}
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
DeveloperToolbarTest.exec({
typed: "console open",
args: {},
blankOutput: true,
completed: false,
});
function onExecute() {
let onExecute = function() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
ok(labels.length > 0, "output for pprint(window)");
DeveloperToolbarTest.exec({
typed: "console clear",
args: {},
blankOutput: true,
helpers.audit(options, [
{
setup: "console clear",
exec: {
output: ""
},
post: function() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
// Bug 845827 - The GCLI "console clear" command doesn't always work
// is(labels.length, 0, "no output in console");
}
},
{
setup: "console close",
exec: {
output: ""
},
post: function() {
ok(!(hud.hudId in HUDService.hudReferences), "console closed");
}
}
]).then(function() {
// FIXME: Remove this hack once bug 842347 is fixed
// Gak - our promises impl causes so many stack frames that we blow up the
// JS engine. Jumping to a new event with a truncated stack solves this.
executeSoon(function() {
deferred.resolve();
});
});
};
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
helpers.audit(options, [
{
setup: "console open",
exec: { }
}
]);
DeveloperToolbarTest.exec({
typed: "console close",
args: {},
blankOutput: true,
});
ok(!(hud.hudId in imported.HUDService.hudReferences), "console closed");
imported = undefined;
}
}
return deferred.promise;
};

Просмотреть файл

@ -6,93 +6,105 @@
const TEST_URI = "data:text/html;charset=utf-8,gcli-cookie";
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testCookieCheck, testCookieExec ]);
}
function testCookieCheck() {
helpers.setInput('cookie');
helpers.check({
input: 'cookie',
hints: '',
markup: 'IIIIII',
status: 'ERROR'
});
helpers.setInput('cookie lis');
helpers.check({
input: 'cookie lis',
hints: 't',
markup: 'IIIIIIVIII',
status: 'ERROR'
});
helpers.setInput('cookie list');
helpers.check({
input: 'cookie list',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('cookie remove');
helpers.check({
input: 'cookie remove',
hints: ' <key>',
markup: 'VVVVVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('cookie set');
helpers.check({
input: 'cookie set',
hints: ' <key> <value> [options]',
markup: 'VVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('cookie set fruit');
helpers.check({
input: 'cookie set fruit',
hints: ' <value> [options]',
markup: 'VVVVVVVVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('cookie set fruit ban');
helpers.check({
input: 'cookie set fruit ban',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
key: { value: 'fruit' },
value: { value: 'ban' },
secure: { value: false },
}
});
}
function testCookieExec() {
DeveloperToolbarTest.exec({
typed: "cookie set fruit banana",
args: {
key: "fruit",
value: "banana",
path: "/",
domain: null,
secure: false
},
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "cookie list",
outputMatch: /Key/
});
DeveloperToolbarTest.exec({
typed: "cookie remove fruit",
args: { key: "fruit" },
blankOutput: true,
});
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.audit(options, [
{
setup: 'cookie',
check: {
input: 'cookie',
hints: '',
markup: 'IIIIII',
status: 'ERROR'
},
},
{
setup: 'cookie lis',
check: {
input: 'cookie lis',
hints: 't',
markup: 'IIIIIIVIII',
status: 'ERROR'
},
},
{
setup: 'cookie list',
check: {
input: 'cookie list',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID'
},
},
{
setup: 'cookie remove',
check: {
input: 'cookie remove',
hints: ' <key>',
markup: 'VVVVVVVVVVVVV',
status: 'ERROR'
},
},
{
setup: 'cookie set',
check: {
input: 'cookie set',
hints: ' <key> <value> [options]',
markup: 'VVVVVVVVVV',
status: 'ERROR'
},
},
{
setup: 'cookie set fruit',
check: {
input: 'cookie set fruit',
hints: ' <value> [options]',
markup: 'VVVVVVVVVVVVVVVV',
status: 'ERROR'
},
},
{
setup: 'cookie set fruit ban',
check: {
input: 'cookie set fruit ban',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
key: { value: 'fruit' },
value: { value: 'ban' },
secure: { value: false },
}
},
},
{
setup: "cookie set fruit banana",
check: {
args: {
key: { value: 'fruit' },
value: { value: 'banana' },
}
},
exec: {
output: ""
}
},
{
setup: "cookie list",
exec: {
output: /Key/
}
},
{
setup: "cookie remove fruit",
check: {
args: {
key: { value: 'fruit' },
}
},
exec: {
output: ""
}
},
]);
}).then(finish);
}

Просмотреть файл

@ -1,51 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that source URLs in the Web Console can be clicked to display the
// standard View Source window.
function test() {
testCreateCommands();
testRemoveCommands();
}
let [ define, require ] = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/devtools/Require.jsm", tempScope);
return [ tempScope.define, tempScope.require ];
})();
registerCleanupFunction(function tearDown() {
define = undefined;
require = undefined;
});
let tselarr = {
name: 'tselarr',
params: [
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
],
exec: function(args, env) {
return "flu " + args.num + "-" + args.arr.join("_");
}
};
function testCreateCommands() {
let gcliIndex = require("gcli/index");
gcliIndex.addCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd != null, "tselarr exists in the canon");
ok(tselcmd instanceof canon.Command, "canon storing commands");
}
function testRemoveCommands() {
let gcliIndex = require("gcli/index");
gcliIndex.removeCommand(tselarr);
let canon = require("gcli/canon");
let tselcmd = canon.getCommand("tselarr");
ok(tselcmd == null, "tselcmd removed from the canon");
}

Просмотреть файл

@ -7,67 +7,80 @@ const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_cmd_jsb_script.jsi";
let scratchpadWin = null;
let Scratchpad = null;
let scratchpad = null;
let tests = {};
function test() {
DeveloperToolbarTest.test("about:blank", [ GJT_test ]);
helpers.addTabWithToolbar("about:blank", function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}
function GJT_test() {
helpers.setInput('jsb');
helpers.check({
input: 'jsb',
hints: ' <url> [options]',
markup: 'VVV',
status: 'ERROR'
});
DeveloperToolbarTest.exec({ completed: false });
tests.jsbTest = function(options) {
let deferred = Promise.defer();
Services.ww.registerNotification(function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
Services.ww.unregisterNotification(arguments.callee);
let observer = {
onReady: function() {
scratchpad.removeObserver(observer);
scratchpadWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
scratchpadWin.addEventListener("load", function GDT_onLoad() {
scratchpadWin.removeEventListener("load", GDT_onLoad, false);
Scratchpad = scratchpadWin.Scratchpad;
let result = scratchpad.getText();
result = result.replace(/[\r\n]]*/g, "\n");
let correct = "function somefunc() {\n" +
" if (true) // Some comment\n" +
" doSomething();\n" +
" for (let n = 0; n < 500; n++) {\n" +
" if (n % 2 == 1) {\n" +
" console.log(n);\n" +
" console.log(n + 1);\n" +
" }\n" +
" }\n" +
"}";
is(result, correct, "JS has been correctly prettified");
let observer = {
onReady: function GJT_onReady() {
Scratchpad.removeObserver(observer);
let result = Scratchpad.getText();
result = result.replace(/[\r\n]]*/g, "\n");
let correct = "function somefunc() {\n" +
" if (true) // Some comment\n" +
" doSomething();\n" +
" for (let n = 0; n < 500; n++) {\n" +
" if (n % 2 == 1) {\n" +
" console.log(n);\n" +
" console.log(n + 1);\n" +
" }\n" +
" }\n" +
"}";
is(result, correct, "JS has been correctly prettified");
finishUp();
},
};
Scratchpad.addObserver(observer);
}, false);
if (scratchpadWin) {
scratchpadWin.close();
scratchpadWin = null;
}
});
deferred.resolve();
},
};
info("Checking beautification");
DeveloperToolbarTest.exec({
typed: "jsb " + TEST_URI,
completed: false
});
}
let onLoad = function GDT_onLoad() {
scratchpadWin.removeEventListener("load", onLoad, false);
scratchpad = scratchpadWin.Scratchpad;
let finishUp = DeveloperToolbarTest.checkCalled(function GJT_finishUp() {
if (scratchpadWin) {
scratchpadWin.close();
scratchpadWin = null;
}
});
scratchpad.addObserver(observer);
};
let onNotify = function(subject, topic, data) {
if (topic == "domwindowopened") {
Services.ww.unregisterNotification(onNotify);
scratchpadWin = subject.QueryInterface(Ci.nsIDOMWindow);
scratchpadWin.addEventListener("load", onLoad, false);
}
};
Services.ww.registerNotification(onNotify);
helpers.audit(options, [
{
setup: 'jsb',
check: {
input: 'jsb',
hints: ' <url> [options]',
markup: 'VVV',
status: 'ERROR'
}
},
{
setup: 'jsb ' + TEST_URI,
// Should result in a new window, which should fire onReady (eventually)
exec: {
completed: false
}
}
]);
return deferred.promise;
};

Просмотреть файл

@ -9,296 +9,368 @@ const TEST_URI = "http://example.com/browser/browser/devtools/commandline/"+
function test() {
let initialHtml = "";
DeveloperToolbarTest.test(TEST_URI, [
init,
testExportHtml,
testPageModReplace,
testPageModRemoveElement,
testPageModRemoveAttribute
]);
var tests = {};
function init() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
initialHtml = content.document.documentElement.innerHTML;
return helpers.runTests(options, tests);
}).then(finish);
function getContent(options) {
return options.document.documentElement.innerHTML;
}
function testExportHtml() {
helpers.setInput('export html');
helpers.check({
input: 'export html',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID'
});
function resetContent(options) {
options.document.documentElement.innerHTML = initialHtml;
}
let oldOpen = content.open;
tests.testExportHtml = function(options) {
let oldOpen = options.window.open;
let openURL = "";
content.open = function(aUrl) {
openURL = aUrl;
options.window.open = function(url) {
// The URL is a data: URL that contains the document source
openURL = decodeURIComponent(url);
};
DeveloperToolbarTest.exec({ blankOutput: true });
return helpers.audit(options, [
{
setup: 'export html',
check: {
input: 'export html',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ''
},
post: function() {
isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
openURL = decodeURIComponent(openURL);
isnot(openURL.indexOf('<html lang="en">'), -1, "export html works: <html>");
isnot(openURL.indexOf("<title>GCLI"), -1, "export html works: <title>");
isnot(openURL.indexOf('<p id="someid">#'), -1, "export html works: <p>");
content.open = oldOpen;
}
function getContent() {
return content.document.documentElement.innerHTML;
}
function resetContent() {
content.document.documentElement.innerHTML = initialHtml;
}
function testPageModReplace() {
helpers.setInput('pagemod replace');
helpers.check({
input: 'pagemod replace',
hints: ' <search> <replace> [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('pagemod replace some foo');
helpers.check({
input: 'pagemod replace some foo',
hints: ' [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('pagemod replace some foo true');
helpers.check({
input: 'pagemod replace some foo true',
hints: ' [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('pagemod replace some foo true --attrOnly');
helpers.check({
input: 'pagemod replace some foo true --attrOnly',
hints: ' [selector] [root] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec({
typed: "pagemod replace sOme foOBar",
outputMatch: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "no change in the page");
DeveloperToolbarTest.exec({
typed: "pagemod replace sOme foOBar true",
outputMatch: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 2\.\s*$/
});
isnot(getContent().indexOf('<p class="foOBarclass">.foOBarclass'), -1,
".someclass changed to .foOBarclass");
isnot(getContent().indexOf('<p id="foOBarid">#foOBarid'), -1,
"#someid changed to #foOBarid");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --contentOnly",
outputMatch: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 0\.\s*$/
});
isnot(getContent().indexOf('<p class="someclass">.foobarclass'), -1,
".someclass changed to .foobarclass (content only)");
isnot(getContent().indexOf('<p id="someid">#foobarid'), -1,
"#someid changed to #foobarid (content only)");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --attrOnly",
outputMatch: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 2\.\s*$/
});
isnot(getContent().indexOf('<p class="foobarclass">.someclass'), -1,
".someclass changed to .foobarclass (attr only)");
isnot(getContent().indexOf('<p id="foobarid">#someid'), -1,
"#someid changed to #foobarid (attr only)");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --root head",
outputMatch: /^[^:]+: 2\. [^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed");
DeveloperToolbarTest.exec({
typed: "pagemod replace some foobar --selector .someclass,div,span",
outputMatch: /^[^:]+: 4\. [^:]+: 1\. [^:]+: 1\.\s*$/
});
isnot(getContent().indexOf('<p class="foobarclass">.foobarclass'), -1,
".someclass changed to .foobarclass");
isnot(getContent().indexOf('<p id="someid">#someid'), -1,
"#someid did not change");
resetContent();
}
function testPageModRemoveElement() {
helpers.setInput('pagemod remove');
helpers.check({
input: 'pagemod remove',
hints: '',
markup: 'IIIIIIIVIIIIII',
status: 'ERROR'
});
helpers.setInput('pagemod remove element');
helpers.check({
input: 'pagemod remove element',
hints: ' <search> [root] [stripOnly] [ifEmptyOnly]',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('pagemod remove element foo');
helpers.check({
input: 'pagemod remove element foo',
hints: ' [root] [stripOnly] [ifEmptyOnly]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec({
typed: "pagemod remove element p",
outputMatch: /^[^:]+: 3\. [^:]+: 3\.\s*$/
});
is(getContent().indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(getContent().indexOf('<p id="someid">'), -1, "p#someid removed");
is(getContent().indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(getContent().indexOf("<span>"), -1, "<span> not removed");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod remove element p head",
outputMatch: /^[^:]+: 0\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove element p --ifEmptyOnly",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
is(getContent(), initialHtml, "nothing changed in the page");
DeveloperToolbarTest.exec({
typed: "pagemod remove element meta,title --ifEmptyOnly",
outputMatch: /^[^:]+: 2\. [^:]+: 1\.\s*$/
});
is(getContent().indexOf("<meta charset="), -1, "<meta> removed");
isnot(getContent().indexOf("<title>"), -1, "<title> not removed");
resetContent();
DeveloperToolbarTest.exec({
typed: "pagemod remove element p --stripOnly",
outputMatch: /^[^:]+: 3\. [^:]+: 3\.\s*$/
});
is(getContent().indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(getContent().indexOf('<p id="someid">'), -1, "p#someid removed");
is(getContent().indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(getContent().indexOf(".someclass"), -1, ".someclass still exists");
isnot(getContent().indexOf("#someid"), -1, "#someid still exists");
isnot(getContent().indexOf("<strong>p"), -1, "<strong> still exists");
resetContent();
}
function testPageModRemoveAttribute() {
helpers.setInput('pagemod remove attribute ');
helpers.check({
input: 'pagemod remove attribute ',
hints: '<searchAttributes> <searchElements> [root] [ignoreCase]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'ERROR',
args: {
searchAttributes: { value: undefined, status: 'INCOMPLETE' },
searchElements: { value: undefined, status: 'INCOMPLETE' },
root: { value: undefined },
ignoreCase: { value: false },
options.window.open = oldOpen;
}
}
});
]);
};
helpers.setInput('pagemod remove attribute foo bar');
helpers.check({
input: 'pagemod remove attribute foo bar',
hints: ' [root] [ignoreCase]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
searchAttributes: { value: 'foo' },
searchElements: { value: 'bar' },
root: { value: undefined },
ignoreCase: { value: false },
}
});
tests.testPageModReplace = function(options) {
return helpers.audit(options, [
{
setup: 'pagemod replace',
check: {
input: 'pagemod replace',
hints: ' <search> <replace> [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVV',
status: 'ERROR'
}
},
{
setup: 'pagemod replace some foo',
check: {
input: 'pagemod replace some foo',
hints: ' [ignoreCase] [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'pagemod replace some foo true',
check: {
input: 'pagemod replace some foo true',
hints: ' [selector] [root] [attrOnly] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'pagemod replace some foo true --attrOnly',
check: {
input: 'pagemod replace some foo true --attrOnly',
hints: ' [selector] [root] [contentOnly] [attributes]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
}
},
{
setup: 'pagemod replace sOme foOBar',
exec: {
output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "no change in the page");
}
},
{
setup: 'pagemod replace sOme foOBar true',
exec: {
output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 2\.\s*$/
},
post: function() {
let html = getContent(options);
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute foo bar",
outputMatch: /^[^:]+: 0\. [^:]+: 0\.\s*$/
});
isnot(html.indexOf('<p class="foOBarclass">.foOBarclass'), -1,
".someclass changed to .foOBarclass");
isnot(html.indexOf('<p id="foOBarid">#foOBarid'), -1,
"#someid changed to #foOBarid");
is(getContent(), initialHtml, "nothing changed in the page");
resetContent(options);
}
},
{
setup: 'pagemod replace some foobar --contentOnly',
exec: {
output: /^[^:]+: 13\. [^:]+: 2\. [^:]+: 0\.\s*$/
},
post: function() {
let html = getContent(options);
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute foo p",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
isnot(html.indexOf('<p class="someclass">.foobarclass'), -1,
".someclass changed to .foobarclass (content only)");
isnot(html.indexOf('<p id="someid">#foobarid'), -1,
"#someid changed to #foobarid (content only)");
is(getContent(), initialHtml, "nothing changed in the page");
resetContent(options);
}
},
{
setup: 'pagemod replace some foobar --attrOnly',
exec: {
output: /^[^:]+: 13\. [^:]+: 0\. [^:]+: 2\.\s*$/
},
post: function() {
let html = getContent(options);
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute id p,span",
outputMatch: /^[^:]+: 5\. [^:]+: 1\.\s*$/
});
isnot(html.indexOf('<p class="foobarclass">.someclass'), -1,
".someclass changed to .foobarclass (attr only)");
isnot(html.indexOf('<p id="foobarid">#someid'), -1,
"#someid changed to #foobarid (attr only)");
is(getContent().indexOf('<p id="someid">#someid'), -1,
"p#someid attribute removed");
isnot(getContent().indexOf("<p>#someid"), -1,
"p with someid content still exists");
resetContent(options);
}
},
{
setup: 'pagemod replace some foobar --root head',
exec: {
output: /^[^:]+: 2\. [^:]+: 0\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed");
}
},
{
setup: 'pagemod replace some foobar --selector .someclass,div,span',
exec: {
output: /^[^:]+: 4\. [^:]+: 1\. [^:]+: 1\.\s*$/
},
post: function() {
let html = getContent(options);
resetContent();
isnot(html.indexOf('<p class="foobarclass">.foobarclass'), -1,
".someclass changed to .foobarclass");
isnot(html.indexOf('<p id="someid">#someid'), -1,
"#someid did not change");
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute Class p",
outputMatch: /^[^:]+: 3\. [^:]+: 0\.\s*$/
});
resetContent(options);
}
},
]);
};
is(getContent(), initialHtml, "nothing changed in the page");
tests.testPageModRemoveElement = function(options) {
return helpers.audit(options, [
{
setup: 'pagemod remove',
check: {
input: 'pagemod remove',
hints: '',
markup: 'IIIIIIIVIIIIII',
status: 'ERROR'
},
},
{
setup: 'pagemod remove element',
check: {
input: 'pagemod remove element',
hints: ' <search> [root] [stripOnly] [ifEmptyOnly]',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
status: 'ERROR'
},
},
{
setup: 'pagemod remove element foo',
check: {
input: 'pagemod remove element foo',
hints: ' [root] [stripOnly] [ifEmptyOnly]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
},
},
{
setup: 'pagemod remove element p',
exec: {
output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
},
post: function() {
let html = getContent(options);
DeveloperToolbarTest.exec({
typed: "pagemod remove attribute Class p --ignoreCase",
outputMatch: /^[^:]+: 3\. [^:]+: 1\.\s*$/
});
is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(html.indexOf("<span>"), -1, "<span> not removed");
is(getContent().indexOf('<p class="someclass">.someclass'), -1,
"p.someclass attribute removed");
isnot(getContent().indexOf("<p>.someclass"), -1,
"p with someclass content still exists");
resetContent(options);
}
},
{
setup: 'pagemod remove element p head',
exec: {
output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed in the page");
}
},
{
setup: 'pagemod remove element p --ifEmptyOnly',
exec: {
output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed in the page");
}
},
{
setup: 'pagemod remove element meta,title --ifEmptyOnly',
exec: {
output: /^[^:]+: 2\. [^:]+: 1\.\s*$/
},
post: function() {
let html = getContent(options);
resetContent();
}
is(html.indexOf("<meta charset="), -1, "<meta> removed");
isnot(html.indexOf("<title>"), -1, "<title> not removed");
resetContent(options);
}
},
{
setup: 'pagemod remove element p --stripOnly',
exec: {
output: /^[^:]+: 3\. [^:]+: 3\.\s*$/
},
post: function() {
let html = getContent(options);
is(html.indexOf('<p class="someclass">'), -1, "p.someclass removed");
is(html.indexOf('<p id="someid">'), -1, "p#someid removed");
is(html.indexOf("<p><strong>"), -1, "<p> wrapping <strong> removed");
isnot(html.indexOf(".someclass"), -1, ".someclass still exists");
isnot(html.indexOf("#someid"), -1, "#someid still exists");
isnot(html.indexOf("<strong>p"), -1, "<strong> still exists");
resetContent(options);
}
},
]);
};
tests.testPageModRemoveAttribute = function(options) {
return helpers.audit(options, [
{
setup: 'pagemod remove attribute',
check: {
input: 'pagemod remove attribute',
hints: ' <searchAttributes> <searchElements> [root] [ignoreCase]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'ERROR',
args: {
searchAttributes: { value: undefined, status: 'INCOMPLETE' },
searchElements: { value: undefined, status: 'INCOMPLETE' },
root: { value: undefined },
ignoreCase: { value: false },
}
},
},
{
setup: 'pagemod remove attribute foo bar',
check: {
input: 'pagemod remove attribute foo bar',
hints: ' [root] [ignoreCase]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
searchAttributes: { value: 'foo' },
searchElements: { value: 'bar' },
root: { value: undefined },
ignoreCase: { value: false },
}
},
post: function() {
let deferred = Promise.defer();
executeSoon(function() {
deferred.resolve();
});
return deferred.promise;
}
},
{
setup: 'pagemod remove attribute foo bar',
exec: {
output: /^[^:]+: 0\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed in the page");
}
},
{
setup: 'pagemod remove attribute foo p',
exec: {
output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed in the page");
}
},
{
setup: 'pagemod remove attribute id p,span',
exec: {
output: /^[^:]+: 5\. [^:]+: 1\.\s*$/
},
post: function() {
is(getContent(options).indexOf('<p id="someid">#someid'), -1,
"p#someid attribute removed");
isnot(getContent(options).indexOf("<p>#someid"), -1,
"p with someid content still exists");
resetContent(options);
}
},
{
setup: 'pagemod remove attribute Class p',
exec: {
output: /^[^:]+: 3\. [^:]+: 0\.\s*$/
},
post: function() {
is(getContent(options), initialHtml, "nothing changed in the page");
}
},
{
setup: 'pagemod remove attribute Class p --ignoreCase',
exec: {
output: /^[^:]+: 3\. [^:]+: 1\.\s*$/
},
post: function() {
is(getContent(options).indexOf('<p class="someclass">.someclass'), -1,
"p.someclass attribute removed");
isnot(getContent(options).indexOf("<p>.someclass"), -1,
"p with someclass content still exists");
resetContent(options);
}
},
]);
};
}

Просмотреть файл

@ -3,420 +3,500 @@
// Tests that the pref commands work
let imports = {};
let prefBranch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService).getBranch(null)
.QueryInterface(Ci.nsIPrefBranch2);
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", imports);
let supportsString = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString)
imports.XPCOMUtils.defineLazyGetter(imports, "prefBranch", function() {
let prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
return prefService.getBranch(null)
.QueryInterface(Components.interfaces.nsIPrefBranch2);
});
let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
imports.XPCOMUtils.defineLazyGetter(imports, "supportsString", function() {
return Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
});
let settings = require("gcli/settings");
const TEST_URI = "data:text/html;charset=utf-8,gcli-pref";
let tiltEnabledOrig;
let tabSizeOrig;
let remoteHostOrig;
let tests = {
setup: function(options) {
tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
remoteHostOrig = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
info("originally: devtools.editor.tabsize = " + tabSizeOrig);
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
},
shutdown: function(options) {
prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
supportsString.data = remoteHostOrig;
prefBranch.setComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString, supportsString);
},
testPrefStatus: function(options) {
return helpers.audit(options, [
{
setup: 'pref',
check: {
input: 'pref',
hints: '',
markup: 'IIII',
status: 'ERROR'
},
},
{
setup: 'pref s',
check: {
input: 'pref s',
hints: 'et',
markup: 'IIIIVI',
status: 'ERROR'
},
},
{
setup: 'pref sh',
check: {
input: 'pref sh',
hints: 'ow',
markup: 'IIIIVII',
status: 'ERROR'
},
},
{
setup: 'pref show ',
check: {
input: 'pref show ',
markup: 'VVVVVVVVVV',
status: 'ERROR'
},
},
{
setup: 'pref show usetexttospeech',
check: {
input: 'pref show usetexttospeech',
hints: ' -> accessibility.usetexttospeech',
markup: 'VVVVVVVVVVIIIIIIIIIIIIIII',
status: 'ERROR'
},
},
{
setup: 'pref show devtools.til',
check: {
input: 'pref show devtools.til',
hints: 't.enabled',
markup: 'VVVVVVVVVVIIIIIIIIIIII',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
setting: { value: undefined, status: 'INCOMPLETE' },
}
},
},
{
setup: 'pref reset devtools.tilt.enabled',
check: {
input: 'pref reset devtools.tilt.enabled',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
},
},
{
setup: 'pref show devtools.tilt.enabled 4',
check: {
input: 'pref show devtools.tilt.enabled 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
status: 'ERROR'
},
},
{
setup: 'pref set devtools.tilt.enabled 4',
check: {
input: 'pref set devtools.tilt.enabled 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
status: 'ERROR',
args: {
setting: { arg: ' devtools.tilt.enabled' },
value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
}
},
},
{
setup: 'pref set devtools.editor.tabsize 4',
check: {
input: 'pref set devtools.editor.tabsize 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
setting: { arg: ' devtools.editor.tabsize' },
value: { value: 4 },
}
},
},
{
setup: 'pref list',
check: {
input: 'pref list',
hints: ' -> pref set',
markup: 'IIIIVIIII',
status: 'ERROR'
},
},
]);
},
testPrefSetEnable: function(options) {
return helpers.audit(options, [
{
setup: 'pref set devtools.editor.tabsize 9',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 9 }
},
},
exec: {
completed: true,
output: [ /void your warranty/, /I promise/ ],
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"),
tabSizeOrig,
"devtools.editor.tabsize is unchanged");
}
},
{
setup: 'pref set devtools.gcli.allowSet true',
check: {
args: {
setting: { value: settings.getSetting("devtools.gcli.allowSet") },
value: { value: true }
},
},
exec: {
completed: true,
output: '',
},
post: function() {
is(prefBranch.getBoolPref("devtools.gcli.allowSet"), true,
"devtools.gcli.allowSet is true");
}
},
{
setup: 'pref set devtools.editor.tabsize 10',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 10 }
},
},
exec: {
completed: true,
output: '',
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"), 10,
"devtools.editor.tabsize is 10");
}
},
]);
},
testPrefBoolExec: function(options) {
return helpers.audit(options, [
{
setup: 'pref show devtools.tilt.enabled',
check: {
args: {
setting: { value: settings.getSetting("devtools.tilt.enabled") }
},
},
exec: {
completed: true,
output: new RegExp("^" + tiltEnabledOrig + "$"),
},
},
{
setup: 'pref set devtools.tilt.enabled true',
check: {
args: {
setting: { value: settings.getSetting("devtools.tilt.enabled") },
value: { value: true }
},
},
exec: {
completed: true,
output: '',
},
post: function() {
is(prefBranch.getBoolPref("devtools.tilt.enabled"), true,
"devtools.tilt.enabled is true");
}
},
{
setup: 'pref show devtools.tilt.enabled',
check: {
args: {
setting: { value: settings.getSetting("devtools.tilt.enabled") }
},
},
exec: {
completed: true,
output: new RegExp("^true$"),
},
},
{
setup: 'pref set devtools.tilt.enabled false',
check: {
args: {
setting: { value: settings.getSetting("devtools.tilt.enabled") },
value: { value: false }
},
},
exec: {
completed: true,
output: '',
},
},
{
setup: 'pref show devtools.tilt.enabled',
check: {
args: {
setting: { value: settings.getSetting("devtools.tilt.enabled") }
},
},
exec: {
completed: true,
output: new RegExp("^false$"),
},
post: function() {
is(prefBranch.getBoolPref("devtools.tilt.enabled"), false,
"devtools.tilt.enabled is false");
}
},
]);
},
testPrefNumberExec: function(options) {
return helpers.audit(options, [
{
setup: 'pref show devtools.editor.tabsize',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") }
},
},
exec: {
completed: true,
output: new RegExp("^10$"),
},
},
{
setup: 'pref set devtools.editor.tabsize 20',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 20 }
},
},
exec: {
completed: true,
output: '',
},
},
{
setup: 'pref show devtools.editor.tabsize',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") }
},
},
exec: {
completed: true,
output: new RegExp("^20$"),
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"), 20,
"devtools.editor.tabsize is 20");
}
},
{
setup: 'pref set devtools.editor.tabsize 1',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 1 }
},
},
exec: {
completed: true,
output: '',
},
},
{
setup: 'pref show devtools.editor.tabsize',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") }
},
},
exec: {
completed: true,
output: new RegExp("^1$"),
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"), 1,
"devtools.editor.tabsize is 1");
}
},
]);
},
testPrefStringExec: function(options) {
return helpers.audit(options, [
{
setup: 'pref show devtools.debugger.remote-host',
check: {
args: {
setting: { value: settings.getSetting("devtools.debugger.remote-host") }
},
},
exec: {
completed: true,
output: new RegExp("^" + remoteHostOrig + "$"),
},
},
{
setup: 'pref set devtools.debugger.remote-host e.com',
check: {
args: {
setting: { value: settings.getSetting("devtools.debugger.remote-host") },
value: { value: "e.com" }
},
},
exec: {
completed: true,
output: '',
},
},
{
setup: 'pref show devtools.debugger.remote-host',
check: {
args: {
setting: { value: settings.getSetting("devtools.debugger.remote-host") }
},
},
exec: {
completed: true,
output: new RegExp("^e.com$"),
},
post: function() {
var ecom = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
}
},
{
setup: 'pref set devtools.debugger.remote-host moz.foo',
check: {
args: {
setting: { value: settings.getSetting("devtools.debugger.remote-host") },
value: { value: "moz.foo" }
},
},
exec: {
completed: true,
output: '',
},
},
{
setup: 'pref show devtools.debugger.remote-host',
check: {
args: {
setting: { value: settings.getSetting("devtools.debugger.remote-host") }
},
},
exec: {
completed: true,
output: new RegExp("^moz.foo$"),
},
post: function() {
var mozfoo = prefBranch.getComplexValue("devtools.debugger.remote-host",
Ci.nsISupportsString).data;
is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
}
},
]);
},
testPrefSetDisable: function(options) {
return helpers.audit(options, [
{
setup: 'pref set devtools.editor.tabsize 32',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 32 }
},
},
exec: {
completed: true,
output: '',
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
"devtools.editor.tabsize is 32");
}
},
{
setup: 'pref reset devtools.gcli.allowSet',
check: {
args: {
setting: { value: settings.getSetting("devtools.gcli.allowSet") }
},
},
exec: {
completed: true,
output: '',
},
post: function() {
is(prefBranch.getBoolPref("devtools.gcli.allowSet"), false,
"devtools.gcli.allowSet is false");
}
},
{
setup: 'pref set devtools.editor.tabsize 33',
check: {
args: {
setting: { value: settings.getSetting("devtools.editor.tabsize") },
value: { value: 33 }
},
},
exec: {
completed: true,
output: [ /void your warranty/, /I promise/ ],
},
post: function() {
is(prefBranch.getIntPref("devtools.editor.tabsize"), 32,
"devtools.editor.tabsize is still 32");
}
},
]);
},
};
function test() {
DeveloperToolbarTest.test(TEST_URI, [
setup,
testPrefSetEnable,
testPrefStatus,
testPrefBoolExec,
testPrefNumberExec,
testPrefStringExec,
testPrefSetDisable,
shutdown
]);
}
let tiltEnabledOrig = undefined;
let tabSizeOrig = undefined;
let remoteHostOrig = undefined;
function setup() {
Components.utils.import("resource://gre/modules/devtools/Require.jsm", imports);
imports.settings = imports.require("gcli/settings");
tiltEnabledOrig = imports.prefBranch.getBoolPref("devtools.tilt.enabled");
tabSizeOrig = imports.prefBranch.getIntPref("devtools.editor.tabsize");
remoteHostOrig = imports.prefBranch.getComplexValue(
"devtools.debugger.remote-host",
Components.interfaces.nsISupportsString).data;
info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
info("originally: devtools.editor.tabsize = " + tabSizeOrig);
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
}
function shutdown() {
imports.prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
imports.prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
imports.supportsString.data = remoteHostOrig;
imports.prefBranch.setComplexValue("devtools.debugger.remote-host",
Components.interfaces.nsISupportsString,
imports.supportsString);
tiltEnabledOrig = undefined;
tabSizeOrig = undefined;
remoteHostOrig = undefined;
imports = undefined;
}
function testPrefStatus() {
helpers.setInput('pref');
helpers.check({
input: 'pref',
hints: '',
markup: 'IIII',
status: 'ERROR'
});
helpers.setInput('pref s');
helpers.check({
input: 'pref s',
hints: 'et',
markup: 'IIIIVI',
status: 'ERROR'
});
helpers.setInput('pref sh');
helpers.check({
input: 'pref sh',
hints: 'ow',
markup: 'IIIIVII',
status: 'ERROR'
});
helpers.setInput('pref show ');
helpers.check({
input: 'pref show ',
markup: 'VVVVVVVVVV',
status: 'ERROR'
});
helpers.setInput('pref show usetexttospeech');
helpers.check({
input: 'pref show usetexttospeech',
hints: ' -> accessibility.usetexttospeech',
markup: 'VVVVVVVVVVIIIIIIIIIIIIIII',
status: 'ERROR'
});
helpers.setInput('pref show devtools.til');
helpers.check({
input: 'pref show devtools.til',
hints: 't.enabled',
markup: 'VVVVVVVVVVIIIIIIIIIIII',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
setting: { value: undefined, status: 'INCOMPLETE' },
}
});
helpers.setInput('pref reset devtools.tilt.enabled');
helpers.check({
input: 'pref reset devtools.tilt.enabled',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID'
});
helpers.setInput('pref show devtools.tilt.enabled 4');
helpers.check({
input: 'pref show devtools.tilt.enabled 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
status: 'ERROR'
});
helpers.setInput('pref set devtools.tilt.enabled 4');
helpers.check({
input: 'pref set devtools.tilt.enabled 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVE',
status: 'ERROR',
args: {
setting: { arg: ' devtools.tilt.enabled' },
value: { status: 'ERROR', message: 'Can\'t use \'4\'.' },
}
});
helpers.setInput('pref set devtools.editor.tabsize 4');
helpers.check({
input: 'pref set devtools.editor.tabsize 4',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
setting: { arg: ' devtools.editor.tabsize' },
value: { value: 4 },
}
});
helpers.setInput('pref list');
helpers.check({
input: 'pref list',
hints: ' -> pref set',
markup: 'IIIIVIIII',
status: 'ERROR'
});
}
function testPrefSetEnable() {
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 9",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: 9
},
completed: true,
outputMatch: [ /void your warranty/, /I promise/ ],
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"),
tabSizeOrig,
"devtools.editor.tabsize is unchanged");
DeveloperToolbarTest.exec({
typed: "pref set devtools.gcli.allowSet true",
args: {
setting: imports.settings.getSetting("devtools.gcli.allowSet"),
value: true
},
completed: true,
blankOutput: true,
});
is(imports.prefBranch.getBoolPref("devtools.gcli.allowSet"), true,
"devtools.gcli.allowSet is true");
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 10",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: 10
},
completed: true,
blankOutput: true,
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"),
10,
"devtools.editor.tabsize is 10");
}
function testPrefBoolExec() {
DeveloperToolbarTest.exec({
typed: "pref show devtools.tilt.enabled",
args: {
setting: imports.settings.getSetting("devtools.tilt.enabled")
},
completed: true,
outputMatch: new RegExp("^" + tiltEnabledOrig + "$"),
});
DeveloperToolbarTest.exec({
typed: "pref set devtools.tilt.enabled true",
args: {
setting: imports.settings.getSetting("devtools.tilt.enabled"),
value: true
},
completed: true,
blankOutput: true,
});
is(imports.prefBranch.getBoolPref("devtools.tilt.enabled"), true,
"devtools.tilt.enabled is true");
DeveloperToolbarTest.exec({
typed: "pref show devtools.tilt.enabled",
args: {
setting: imports.settings.getSetting("devtools.tilt.enabled")
},
completed: true,
outputMatch: new RegExp("^true$"),
});
DeveloperToolbarTest.exec({
typed: "pref set devtools.tilt.enabled false",
args: {
setting: imports.settings.getSetting("devtools.tilt.enabled"),
value: false
},
completed: true,
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "pref show devtools.tilt.enabled",
args: {
setting: imports.settings.getSetting("devtools.tilt.enabled")
},
completed: true,
outputMatch: new RegExp("^false$"),
});
is(imports.prefBranch.getBoolPref("devtools.tilt.enabled"), false,
"devtools.tilt.enabled is false");
}
function testPrefNumberExec() {
DeveloperToolbarTest.exec({
typed: "pref show devtools.editor.tabsize",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize")
},
completed: true,
outputMatch: new RegExp("^10$"),
});
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 20",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: 20
},
completed: true,
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "pref show devtools.editor.tabsize",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize")
},
completed: true,
outputMatch: new RegExp("^20$"),
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 20,
"devtools.editor.tabsize is 20");
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 1",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: true
},
completed: true,
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "pref show devtools.editor.tabsize",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize")
},
completed: true,
outputMatch: new RegExp("^1$"),
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 1,
"devtools.editor.tabsize is 1");
}
function testPrefStringExec() {
DeveloperToolbarTest.exec({
typed: "pref show devtools.debugger.remote-host",
args: {
setting: imports.settings.getSetting("devtools.debugger.remote-host")
},
completed: true,
outputMatch: new RegExp("^" + remoteHostOrig + "$"),
});
DeveloperToolbarTest.exec({
typed: "pref set devtools.debugger.remote-host e.com",
args: {
setting: imports.settings.getSetting("devtools.debugger.remote-host"),
value: "e.com"
},
completed: true,
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "pref show devtools.debugger.remote-host",
args: {
setting: imports.settings.getSetting("devtools.debugger.remote-host")
},
completed: true,
outputMatch: new RegExp("^e.com$"),
});
var ecom = imports.prefBranch.getComplexValue(
"devtools.debugger.remote-host",
Components.interfaces.nsISupportsString).data;
is(ecom, "e.com", "devtools.debugger.remote-host is e.com");
DeveloperToolbarTest.exec({
typed: "pref set devtools.debugger.remote-host moz.foo",
args: {
setting: imports.settings.getSetting("devtools.debugger.remote-host"),
value: "moz.foo"
},
completed: true,
blankOutput: true,
});
DeveloperToolbarTest.exec({
typed: "pref show devtools.debugger.remote-host",
args: {
setting: imports.settings.getSetting("devtools.debugger.remote-host")
},
completed: true,
outputMatch: new RegExp("^moz.foo$"),
});
var mozfoo = imports.prefBranch.getComplexValue(
"devtools.debugger.remote-host",
Components.interfaces.nsISupportsString).data;
is(mozfoo, "moz.foo", "devtools.debugger.remote-host is moz.foo");
}
function testPrefSetDisable() {
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 32",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: 32
},
completed: true,
blankOutput: true,
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 32,
"devtools.editor.tabsize is 32");
DeveloperToolbarTest.exec({
typed: "pref reset devtools.gcli.allowSet",
args: {
setting: imports.settings.getSetting("devtools.gcli.allowSet")
},
completed: true,
blankOutput: true,
});
is(imports.prefBranch.getBoolPref("devtools.gcli.allowSet"), false,
"devtools.gcli.allowSet is false");
DeveloperToolbarTest.exec({
typed: "pref set devtools.editor.tabsize 33",
args: {
setting: imports.settings.getSetting("devtools.editor.tabsize"),
value: 33
},
completed: true,
outputMatch: [ /void your warranty/, /I promise/ ],
});
is(imports.prefBranch.getIntPref("devtools.editor.tabsize"), 32,
"devtools.editor.tabsize is still 32");
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}

Просмотреть файл

@ -6,27 +6,30 @@
const TEST_URI = "data:text/html;charset=utf-8,gcli-command-restart";
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testRestart ]);
}
function testRestart() {
helpers.setInput('restart');
helpers.check({
input: 'restart',
markup: 'VVVVVVV',
status: 'VALID',
args: {
nocache: { value: false },
}
});
helpers.setInput('restart --nocache');
helpers.check({
input: 'restart --nocache',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
nocache: { value: true },
}
});
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.audit(options, [
{
setup: 'restart',
check: {
input: 'restart',
markup: 'VVVVVVV',
status: 'VALID',
args: {
nocache: { value: false },
}
},
},
{
setup: 'restart --nocache',
check: {
input: 'restart --nocache',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
nocache: { value: true },
}
},
},
]);
}).then(finish);
}

Просмотреть файл

@ -0,0 +1,195 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that screenshot command works properly
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_cmd_screenshot.html";
let FileUtils = (Cu.import("resource://gre/modules/FileUtils.jsm", {})).FileUtils;
let tests = {
testInput: function(options) {
return helpers.audit(options, [
{
setup: 'screenshot',
check: {
input: 'screenshot',
markup: 'VVVVVVVVVV',
status: 'VALID',
args: {
}
},
},
{
setup: 'screenshot abc.png',
check: {
input: 'screenshot abc.png',
markup: 'VVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc.png"},
}
},
},
{
setup: 'screenshot --fullpage',
check: {
input: 'screenshot --fullpage',
markup: 'VVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
fullpage: { value: true},
}
},
},
{
setup: 'screenshot abc --delay 5',
check: {
input: 'screenshot abc --delay 5',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc"},
delay: { value: 5 },
}
},
},
{
setup: 'screenshot --selector img#testImage',
check: {
input: 'screenshot --selector img#testImage',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: {
value: options.window.document.getElementById("testImage")
},
}
},
},
]);
},
testCaptureFile: function(options) {
let file = FileUtils.getFile("TmpD", [ "TestScreenshotFile.png" ]);
return helpers.audit(options, [
{
setup: 'screenshot ' + file.path,
check: {
args: {
filename: { value: "" + file.path },
fullpage: { value: false },
clipboard: { value: false },
chrome: { value: false },
},
},
exec: {
output: new RegExp("^Saved to "),
},
post: function() {
// Bug 849168: screenshot command tests fail in try but not locally
// ok(file.exists(), "Screenshot file exists");
if (file.exists()) {
file.remove(false);
}
}
},
]);
},
testCaptureClipboard: function(options) {
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
let trans = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
trans.init(null);
trans.addDataFlavor("image/png");
return helpers.audit(options, [
{
setup: 'screenshot --fullpage --clipboard',
check: {
args: {
fullpage: { value: true },
clipboard: { value: true },
chrome: { value: false },
},
},
exec: {
output: new RegExp("^Copied to clipboard.$"),
},
post: function() {
try {
clip.getData(trans, clipid.kGlobalClipboard);
let str = new Object();
let strLength = new Object();
trans.getTransferData("image/png", str, strLength);
ok(str.value, "screenshot exists");
ok(strLength.value > 0, "screenshot has length");
}
finally {
Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
// Recent PB changes to the test I'm modifying removed the 'pb'
// variable, but left this line in tact. This seems so obviously
// wrong that I'm leaving this in in case the analysis is wrong
// pb.privateBrowsingEnabled = true;
}
}
},
]);
},
};
function test() {
info("RUN TEST: non-private window");
let nonPrivDone = addWindow({ private: false }, addTabWithToolbarRunTests);
let privDone = nonPrivDone.then(function() {
info("RUN TEST: private window");
return addWindow({ private: true }, addTabWithToolbarRunTests);
});
privDone.then(finish, function(error) {
ok(false, 'Promise fail: ' + error);
});
}
function addTabWithToolbarRunTests(win) {
return helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}, { chromeWindow: win });
}
function addWindow(windowOptions, callback) {
waitForExplicitFinish();
let deferred = Promise.defer();
let win = OpenBrowserWindow(windowOptions);
let onLoad = function() {
win.removeEventListener("load", onLoad, false);
// Would like to get rid of this executeSoon, but without it the url
// (TEST_URI) provided in addTabWithToolbarRunTests hasn't loaded
executeSoon(function() {
try {
let reply = callback(win);
Promise.resolve(reply).then(function() {
win.close();
deferred.resolve();
});
}
catch (ex) {
deferred.reject(ex);
}
});
};
win.addEventListener("load", onLoad, false);
return deferred.promise;
}

Просмотреть файл

@ -1,190 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that screenshot command works properly
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_cmd_screenshot.html";
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
let FileUtils = Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
function test() {
waitForExplicitFinish();
let windowsToClose = [];
Services.prefs.setIntPref("browser.startup.page", 0);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.startup.page");
windowsToClose.forEach(function(win) {
win.close();
});
});
function testOnWindow(aPrivate, aCallback) {
let win = OpenBrowserWindow({private: aPrivate});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(function() aCallback(win));
}, false);
};
testOnWindow(false, function(win) {
info("Testing on public window");
windowsToClose.push(win);
DeveloperToolbarTestPW.test(win, TEST_URI, [ testInput, testCapture ], null, function() {
testOnWindow(true, function(win) {
info("Testing on private window");
windowsToClose.push(win);
DeveloperToolbarTestPW.test(win, TEST_URI, [ testInput, testCapture ], null, finish);
});
});
});
}
function testInput(aWindow, aCallback) {
helpers_perwindowpb.setInput('screenshot');
helpers_perwindowpb.check({
input: 'screenshot',
markup: 'VVVVVVVVVV',
status: 'VALID',
args: { }
});
helpers_perwindowpb.setInput('screenshot abc.png');
helpers_perwindowpb.check({
input: 'screenshot abc.png',
markup: 'VVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc.png"},
}
});
helpers_perwindowpb.setInput('screenshot --fullpage');
helpers_perwindowpb.check({
input: 'screenshot --fullpage',
markup: 'VVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
fullpage: { value: true},
}
});
helpers_perwindowpb.setInput('screenshot abc --delay 5');
helpers_perwindowpb.check({
input: 'screenshot abc --delay 5',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
filename: { value: "abc"},
delay: { value: "5"},
}
});
helpers_perwindowpb.setInput('screenshot --selector img#testImage');
helpers_perwindowpb.check({
input: 'screenshot --selector img#testImage',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { value: aWindow.content.document.getElementById("testImage")},
}
});
aCallback();
}
function testCapture(aWindow, aCallback) {
function checkTemporaryFile() {
// Create a temporary file.
let gFile = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]);
if (gFile.exists()) {
gFile.remove(false);
return true;
}
else {
return false;
}
}
let captureTest = 3;
function captureTestFinish() {
if (captureTest == 0) {
aCallback();
}
}
function checkClipboard() {
try {
let clipid = Ci.nsIClipboard;
let clip = Cc["@mozilla.org/widget/clipboard;1"].getService(clipid);
let trans = Cc["@mozilla.org/widget/transferable;1"]
.createInstance(Ci.nsITransferable);
trans.init(null);
trans.addDataFlavor("image/png");
clip.getData(trans, clipid.kGlobalClipboard);
let str = new Object();
let strLength = new Object();
trans.getTransferData("image/png", str, strLength);
if (str.value && strLength.value > 0) {
return true;
}
}
catch (ex) {}
return false;
}
let path = FileUtils.getFile("TmpD", ["TestScreenshotFile.png"]).path;
DeveloperToolbarTestPW.exec(aWindow, {
typed: "screenshot " + path,
args: {
delay: 0,
filename: "" + path,
fullpage: false,
clipboard: false,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Saved to "),
});
executeSoon(function() {
ok(checkTemporaryFile(), "Screenshot got created");
captureTest--;
captureTestFinish();
});
DeveloperToolbarTestPW.exec(aWindow, {
typed: "screenshot --fullpage --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: true,
clipboard: true,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
});
ok(checkClipboard(), "Screenshot got created and copied");
captureTest--;
DeveloperToolbarTestPW.exec(aWindow, {
typed: "screenshot --clipboard",
args: {
delay: 0,
filename: " ",
fullpage: false,
clipboard: true,
node: null,
chrome: false,
},
outputMatch: new RegExp("^Copied to clipboard.$"),
});
ok(checkClipboard(), "Screenshot present in clipboard");
captureTest--;
captureTestFinish();
}

Просмотреть файл

@ -3,28 +3,19 @@
// Tests that the pref commands work
let imports = {};
let prefBranch = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefService).getBranch(null)
.QueryInterface(Ci.nsIPrefBranch2);
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", imports);
let supportsString = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString)
imports.XPCOMUtils.defineLazyGetter(imports, "prefBranch", function() {
let prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
return prefService.getBranch(null)
.QueryInterface(Components.interfaces.nsIPrefBranch2);
});
let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
imports.XPCOMUtils.defineLazyGetter(imports, "supportsString", function() {
return Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
});
let settings = require("gcli/settings");
const TEST_URI = "data:text/html;charset=utf-8,gcli-settings";
function test() {
DeveloperToolbarTest.test(TEST_URI, [ setup, testSettings, shutdown ]);
}
let tiltEnabled = undefined;
let tabSize = undefined;
let remoteHost = undefined;
@ -33,32 +24,31 @@ let tiltEnabledOrig = undefined;
let tabSizeOrig = undefined;
let remoteHostOrig = undefined;
function setup() {
Components.utils.import("resource://gre/modules/devtools/Require.jsm", imports);
imports.settings = imports.require("gcli/settings");
let tests = {};
tiltEnabled = imports.settings.getSetting("devtools.tilt.enabled");
tabSize = imports.settings.getSetting("devtools.editor.tabsize");
remoteHost = imports.settings.getSetting("devtools.debugger.remote-host");
tests.setup = function() {
tiltEnabled = settings.getSetting("devtools.tilt.enabled");
tabSize = settings.getSetting("devtools.editor.tabsize");
remoteHost = settings.getSetting("devtools.debugger.remote-host");
tiltEnabledOrig = imports.prefBranch.getBoolPref("devtools.tilt.enabled");
tabSizeOrig = imports.prefBranch.getIntPref("devtools.editor.tabsize");
remoteHostOrig = imports.prefBranch.getComplexValue(
tiltEnabledOrig = prefBranch.getBoolPref("devtools.tilt.enabled");
tabSizeOrig = prefBranch.getIntPref("devtools.editor.tabsize");
remoteHostOrig = prefBranch.getComplexValue(
"devtools.debugger.remote-host",
Components.interfaces.nsISupportsString).data;
info("originally: devtools.tilt.enabled = " + tiltEnabledOrig);
info("originally: devtools.editor.tabsize = " + tabSizeOrig);
info("originally: devtools.debugger.remote-host = " + remoteHostOrig);
}
};
function shutdown() {
imports.prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
imports.prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
imports.supportsString.data = remoteHostOrig;
imports.prefBranch.setComplexValue("devtools.debugger.remote-host",
tests.shutdown = function() {
prefBranch.setBoolPref("devtools.tilt.enabled", tiltEnabledOrig);
prefBranch.setIntPref("devtools.editor.tabsize", tabSizeOrig);
supportsString.data = remoteHostOrig;
prefBranch.setComplexValue("devtools.debugger.remote-host",
Components.interfaces.nsISupportsString,
imports.supportsString);
supportsString);
tiltEnabled = undefined;
tabSize = undefined;
@ -67,11 +57,9 @@ function shutdown() {
tiltEnabledOrig = undefined;
tabSizeOrig = undefined;
remoteHostOrig = undefined;
};
imports = undefined;
}
function testSettings() {
tests.testSettings = function() {
is(tiltEnabled.value, tiltEnabledOrig, "tiltEnabled default");
is(tabSize.value, tabSizeOrig, "tabSize default");
is(remoteHost.value, remoteHostOrig, "remoteHost default");
@ -139,4 +127,10 @@ function testSettings() {
is(tiltEnabled.value, tiltEnabledDefault, "tiltEnabled reset");
is(tabSize.value, tabSizeDefault, "tabSize reset");
is(remoteHost.value, remoteHostDefault, "remoteHost reset");
};
function test() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, tests);
}).then(finish);
}

Просмотреть файл

@ -1,116 +0,0 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
function test() {
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_dbg_cmd.html";
DeveloperToolbarTest.test(TEST_URI, function() {
testDbgCmd();
});
}
function testCommands(dbg, cmd) {
// Wait for the initial resume...
dbg._controller.activeThread.addOneTimeListener("resumed", function () {
info("Starting tests");
let contentDoc = content.window.document;
let output = contentDoc.querySelector("input[type=text]");
let btnDoit = contentDoc.querySelector("input[type=button]");
DeveloperToolbarTest.exec({
typed: "dbg list",
outputMatch: /browser_dbg_cmd.html/
});
cmd("dbg interrupt", function() {
ok(true, "debugger is paused");
dbg._controller.activeThread.addOneTimeListener("resumed", function () {
ok(true, "debugger continued");
dbg._controller.activeThread.addOneTimeListener("paused", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
is(output.value, "step in", "debugger stepped in");
cmd("dbg step over", function() {
is(output.value, "step over", "debugger stepped over");
cmd("dbg step out", function() {
is(output.value, "step out", "debugger stepped out");
cmd("dbg continue", function() {
cmd("dbg continue", function() {
is(output.value, "dbg continue", "debugger continued");
DeveloperToolbarTest.exec({
typed: "dbg close",
completed: false,
blankOutput: true
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
if (!toolbox) {
ok(true, "Debugger was closed.");
finish();
} else {
toolbox.on("destroyed", function () {
ok(true, "Debugger was closed.");
finish();
});
}
});
});
});
});
});
});
});
});
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
});
DeveloperToolbarTest.exec({
typed: "dbg continue",
blankOutput: true
});
});
});
}
function testDbgCmd() {
let output = DeveloperToolbarTest.exec({
typed: "dbg open",
blankOutput: true,
completed: false,
});
output.onChange.add(onOpenComplete);
}
function onOpenComplete(ev) {
let output = ev.output;
output.onChange.remove(onOpenComplete);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
function cmd(aTyped, aCallback) {
dbg._controller.activeThread.addOneTimeListener("paused", aCallback);
DeveloperToolbarTest.exec({
typed: aTyped,
blankOutput: true
});
}
if (dbg._controller.activeThread) {
testCommands(dbg, cmd);
} else {
dbg.once("connected", testCommands.bind(null, dbg, cmd));
}
});
}

Просмотреть файл

@ -1,121 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the break command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/commandline/" +
"test/browser_dbg_cmd_break.html";
let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testBreakCommands ]);
}
function testBreakCommands() {
helpers.setInput('break');
helpers.check({
input: 'break',
hints: '',
markup: 'IIIII',
status: 'ERROR'
});
helpers.setInput('break add');
helpers.check({
input: 'break add',
hints: '',
markup: 'IIIIIVIII',
status: 'ERROR'
});
helpers.setInput('break add line');
helpers.check({
input: 'break add line',
hints: ' <file> <line>',
markup: 'VVVVVVVVVVVVVV',
status: 'ERROR'
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
dbg.once("connected", function() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
dbg._view.Variables.lazyEmpty = false;
var client = dbg.panelWin.gClient;
var framesAdded = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break add line ' + TEST_URI + ' ' + content.wrappedJSObject.line0);
helpers.check({
hints: '',
status: 'VALID',
args: {
file: { value: TEST_URI },
line: { value: content.wrappedJSObject.line0 },
}
});
DeveloperToolbarTest.exec({
args: {
type: 'line',
file: TEST_URI,
line: content.wrappedJSObject.line0
},
completed: false
});
helpers.setInput('break list');
helpers.check({
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
var cleanup = DeveloperToolbarTest.checkCalled(function() {
helpers.setInput('break del 9');
helpers.check({
input: 'break del 9',
hints: '',
markup: 'VVVVVVVVVVE',
status: 'ERROR',
args: {
breakid: { status: 'ERROR', message: '9 is greater than maximum allowed: 0.' },
}
});
helpers.setInput('break del 0');
helpers.check({
input: 'break del 0',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID',
args: {
breakid: { value: 0 },
}
});
DeveloperToolbarTest.exec({
args: { breakid: 0 },
completed: false
});
});
client.activeThread.resume(cleanup);
});
client.activeThread.addOneTimeListener("framesadded", framesAdded);
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
});
});
}

Просмотреть файл

@ -0,0 +1,169 @@
/*
* 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(function(require, exports, module) {
// <INJECTED SOURCE:START>
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testAsync.js</p>";
function test() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var helpers = require('gclitest/helpers');
var canon = require('gcli/canon');
var Promise = require('util/promise');
exports.testBasic = function(options) {
var getData = function() {
var deferred = Promise.defer();
var resolve = function() {
deferred.resolve([
'Shalom', 'Namasté', 'Hallo', 'Dydd-da',
'Chào', 'Hej', 'Saluton', 'Sawubona'
]);
};
setTimeout(resolve, 10);
return deferred.promise;
};
var tsslow = {
name: 'tsslow',
params: [
{
name: 'hello',
type: {
name: 'selection',
data: getData
}
}
],
exec: function(args, context) {
return 'Test completed';
}
};
canon.addCommand(tsslow);
return helpers.audit(options, [
{
setup: 'tsslo',
check: {
input: 'tsslo',
hints: 'w',
markup: 'IIIII',
cursor: 5,
current: '__command',
status: 'ERROR',
predictions: ['tsslow'],
unassigned: [ ]
}
},
{
setup: 'tsslo<TAB>',
check: {
input: 'tsslow ',
hints: 'Shalom',
markup: 'VVVVVVV',
cursor: 7,
current: 'hello',
status: 'ERROR',
predictions: [
'Shalom', 'Namasté', 'Hallo', 'Dydd-da', 'Chào', 'Hej',
'Saluton', 'Sawubona'
],
unassigned: [ ],
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tsslow' },
hello: {
value: undefined,
arg: '',
status: 'INCOMPLETE',
message: ''
},
}
}
},
{
setup: 'tsslow S',
check: {
input: 'tsslow S',
hints: 'halom',
markup: 'VVVVVVVI',
cursor: 8,
current: 'hello',
status: 'ERROR',
predictions: [ 'Shalom', 'Saluton', 'Sawubona', 'Namasté' ],
unassigned: [ ],
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tsslow' },
hello: {
value: undefined,
arg: ' S',
status: 'INCOMPLETE',
message: ''
},
}
}
},
{
skipIf: options.isJsdom,
setup: 'tsslow S<TAB>',
check: {
input: 'tsslow Shalom ',
hints: '',
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'hello',
status: 'VALID',
predictions: [ 'Shalom' ],
unassigned: [ ],
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tsslow' },
hello: {
value: 'Shalom',
arg: ' Shalom ',
status: 'VALID',
message: ''
},
}
},
post: function() {
canon.removeCommand(tsslow);
}
},
{
skipIf: options.isJsdom,
setup: 'tsslow ',
check: {
input: 'tsslow ',
markup: 'EEEEEEV',
cursor: 7,
status: 'ERROR'
}
}
]);
};
// });

Просмотреть файл

@ -26,129 +26,178 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCanon.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
// var helpers = require('gclitest/helpers');
var canon = require('gcli/canon');
// var assert = require('test/assert');
'use strict';
exports.setup = function(options) {
helpers.setup(options);
};
// var helpers = require('gclitest/helpers');
var canon = require('gcli/canon');
// var assert = require('test/assert');
exports.shutdown = function(options) {
helpers.shutdown(options);
};
var startCount = undefined;
var events = undefined;
exports.testAddRemove = function(options) {
var startCount = canon.getCommands().length;
var events = 0;
var canonChange = function(ev) {
events++;
};
var canonChange = function(ev) {
events++;
};
canon.onCanonChange.add(canonChange);
exports.setup = function(options) {
startCount = canon.getCommands().length;
events = 0;
};
canon.addCommand({
name: 'testadd',
exec: function() {
return 1;
exports.shutdown = function(options) {
startCount = undefined;
events = undefined;
};
exports.testAddRemove1 = function(options) {
return helpers.audit(options, [
{
name: 'testadd add',
setup: function() {
canon.onCanonChange.add(canonChange);
canon.addCommand({
name: 'testadd',
exec: function() {
return 1;
}
});
assert.is(canon.getCommands().length,
startCount + 1,
'add command success');
assert.is(events, 1, 'add event');
return helpers.setInput(options, 'testadd');
},
check: {
input: 'testadd',
hints: '',
markup: 'VVVVVVV',
cursor: 7,
current: '__command',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: { }
},
exec: {
output: /^1$/
}
});
assert.is(canon.getCommands().length,
startCount + 1,
'add command success');
assert.is(events, 1, 'add event');
helpers.exec({
typed: 'testadd',
outputMatch: /^1$/
});
},
{
name: 'testadd alter',
setup: function() {
canon.addCommand({
name: 'testadd',
exec: function() {
return 2;
}
});
canon.addCommand({
name: 'testadd',
exec: function() {
return 2;
assert.is(canon.getCommands().length,
startCount + 1,
'read command success');
assert.is(events, 2, 'read event');
return helpers.setInput(options, 'testadd');
},
check: {
input: 'testadd',
hints: '',
markup: 'VVVVVVV',
},
exec: {
output: '2'
}
});
},
{
name: 'testadd remove',
setup: function() {
canon.removeCommand('testadd');
assert.is(canon.getCommands().length,
startCount + 1,
'readd command success');
assert.is(events, 2, 'readd event');
helpers.exec({
typed: 'testadd',
outputMatch: /^2$/
});
assert.is(canon.getCommands().length,
startCount,
'remove command success');
assert.is(events, 3, 'remove event');
canon.removeCommand('testadd');
assert.is(canon.getCommands().length,
startCount,
'remove command success');
assert.is(events, 3, 'remove event');
helpers.setInput('testadd');
helpers.check({
typed: 'testadd',
status: 'ERROR'
});
canon.addCommand({
name: 'testadd',
exec: function() {
return 3;
return helpers.setInput(options, 'testadd');
},
check: {
typed: 'testadd',
cursor: 7,
current: '__command',
status: 'ERROR',
unassigned: [ ],
}
});
}
]);
};
assert.is(canon.getCommands().length,
startCount + 1,
'rereadd command success');
assert.is(events, 4, 'rereadd event');
helpers.exec({
typed: 'testadd',
outputMatch: /^3$/
});
exports.testAddRemove2 = function(options) {
canon.addCommand({
name: 'testadd',
exec: function() {
return 3;
}
});
canon.removeCommand({
name: 'testadd'
});
assert.is(canon.getCommands().length,
startCount + 1,
'rereadd command success');
assert.is(events, 4, 'rereadd event');
assert.is(canon.getCommands().length,
startCount,
'reremove command success');
assert.is(events, 5, 'reremove event');
return helpers.audit(options, [
{
setup: 'testadd',
check: {
},
exec: {
output: /^3$/
},
post: function() {
canon.removeCommand({
name: 'testadd'
});
helpers.setInput('testadd');
helpers.check({
typed: 'testadd',
status: 'ERROR'
});
assert.is(canon.getCommands().length,
startCount,
'reremove command success');
assert.is(events, 5, 'reremove event');
}
},
{
setup: 'testadd',
check: {
typed: 'testadd',
status: 'ERROR'
}
}
]);
};
canon.removeCommand({ name: 'nonexistant' });
assert.is(canon.getCommands().length,
startCount,
'nonexistant1 command success');
assert.is(events, 5, 'nonexistant1 event');
exports.testAddRemove3 = function(options) {
canon.removeCommand({ name: 'nonexistant' });
assert.is(canon.getCommands().length,
startCount,
'nonexistant1 command success');
assert.is(events, 5, 'nonexistant1 event');
canon.removeCommand('nonexistant');
assert.is(canon.getCommands().length,
startCount,
'nonexistant2 command success');
assert.is(events, 5, 'nonexistant2 event');
canon.removeCommand('nonexistant');
assert.is(canon.getCommands().length,
startCount,
'nonexistant2 command success');
assert.is(events, 5, 'nonexistant2 event');
canon.onCanonChange.remove(canonChange);
};
canon.onCanonChange.remove(canonChange);
};
// });

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -26,433 +26,511 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testCompletion.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var test = require('test/assert');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function(options) {
mockCommands.setup();
helpers.setup(options);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
helpers.shutdown(options);
};
exports.testActivate = function(options) {
if (!options.display) {
test.log('No display. Skipping activate tests');
return;
}
helpers.setInput('');
helpers.check({
hints: ''
});
helpers.setInput(' ');
helpers.check({
hints: ''
});
helpers.setInput('tsr');
helpers.check({
hints: ' <text>'
});
helpers.setInput('tsr ');
helpers.check({
hints: '<text>'
});
helpers.setInput('tsr b');
helpers.check({
hints: ''
});
helpers.setInput('tsb');
helpers.check({
hints: ' [toggle]'
});
helpers.setInput('tsm');
helpers.check({
hints: ' <abc> <txt> <num>'
});
helpers.setInput('tsm ');
helpers.check({
hints: 'a <txt> <num>'
});
helpers.setInput('tsm a');
helpers.check({
hints: ' <txt> <num>'
});
helpers.setInput('tsm a ');
helpers.check({
hints: '<txt> <num>'
});
helpers.setInput('tsm a ');
helpers.check({
hints: '<txt> <num>'
});
helpers.setInput('tsm a d');
helpers.check({
hints: ' <num>'
});
helpers.setInput('tsm a "d d"');
helpers.check({
hints: ' <num>'
});
helpers.setInput('tsm a "d ');
helpers.check({
hints: ' <num>'
});
helpers.setInput('tsm a "d d" ');
helpers.check({
hints: '<num>'
});
helpers.setInput('tsm a "d d ');
helpers.check({
hints: ' <num>'
});
helpers.setInput('tsm d r');
helpers.check({
hints: ' <num>'
});
helpers.setInput('tsm a d ');
helpers.check({
hints: '<num>'
});
helpers.setInput('tsm a d 4');
helpers.check({
hints: ''
});
helpers.setInput('tsg');
helpers.check({
hints: ' <solo> [options]'
});
helpers.setInput('tsg ');
helpers.check({
hints: 'aaa [options]'
});
helpers.setInput('tsg a');
helpers.check({
hints: 'aa [options]'
});
helpers.setInput('tsg b');
helpers.check({
hints: 'bb [options]'
});
helpers.setInput('tsg d');
helpers.check({
hints: ' [options] -> ccc'
});
helpers.setInput('tsg aa');
helpers.check({
hints: 'a [options]'
});
helpers.setInput('tsg aaa');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsg aaa ');
helpers.check({
hints: '[options]'
});
helpers.setInput('tsg aaa d');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsg aaa dddddd');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsg aaa dddddd ');
helpers.check({
hints: '[options]'
});
helpers.setInput('tsg aaa "d');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsg aaa "d d');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsg aaa "d d"');
helpers.check({
hints: ' [options]'
});
helpers.setInput('tsn ex ');
helpers.check({
hints: ''
});
helpers.setInput('selarr');
helpers.check({
hints: ' -> tselarr'
});
helpers.setInput('tselar 1');
helpers.check({
hints: ''
});
helpers.setInput('tselar 1', 7);
helpers.check({
hints: ''
});
helpers.setInput('tselar 1', 6);
helpers.check({
hints: ' -> tselarr'
});
helpers.setInput('tselar 1', 5);
helpers.check({
hints: ' -> tselarr'
});
return helpers.audit(options, [
{
setup: '',
check: {
hints: ''
}
},
{
setup: ' ',
check: {
hints: ''
}
},
{
setup: 'tsr',
check: {
hints: ' <text>'
}
},
{
setup: 'tsr ',
check: {
hints: '<text>'
}
},
{
setup: 'tsr b',
check: {
hints: ''
}
},
{
setup: 'tsb',
check: {
hints: ' [toggle]'
}
},
{
setup: 'tsm',
check: {
hints: ' <abc> <txt> <num>'
}
},
{
setup: 'tsm ',
check: {
hints: 'a <txt> <num>'
}
},
{
setup: 'tsm a',
check: {
hints: ' <txt> <num>'
}
},
{
setup: 'tsm a ',
check: {
hints: '<txt> <num>'
}
},
{
setup: 'tsm a ',
check: {
hints: '<txt> <num>'
}
},
{
setup: 'tsm a d',
check: {
hints: ' <num>'
}
},
{
setup: 'tsm a "d d"',
check: {
hints: ' <num>'
}
},
{
setup: 'tsm a "d ',
check: {
hints: ' <num>'
}
},
{
setup: 'tsm a "d d" ',
check: {
hints: '<num>'
}
},
{
setup: 'tsm a "d d ',
check: {
hints: ' <num>'
}
},
{
setup: 'tsm d r',
check: {
hints: ' <num>'
}
},
{
setup: 'tsm a d ',
check: {
hints: '<num>'
}
},
{
setup: 'tsm a d 4',
check: {
hints: ''
}
},
{
setup: 'tsg',
check: {
hints: ' <solo> [options]'
}
},
{
setup: 'tsg ',
check: {
hints: 'aaa [options]'
}
},
{
setup: 'tsg a',
check: {
hints: 'aa [options]'
}
},
{
setup: 'tsg b',
check: {
hints: 'bb [options]'
}
},
{
skipIf: options.isPhantomjs,
setup: 'tsg d',
check: {
hints: ' [options] -> ccc'
}
},
{
setup: 'tsg aa',
check: {
hints: 'a [options]'
}
},
{
setup: 'tsg aaa',
check: {
hints: ' [options]'
}
},
{
setup: 'tsg aaa ',
check: {
hints: '[options]'
}
},
{
setup: 'tsg aaa d',
check: {
hints: ' [options]'
}
},
{
setup: 'tsg aaa dddddd',
check: {
hints: ' [options]'
}
},
{
setup: 'tsg aaa dddddd ',
check: {
hints: '[options]'
}
},
{
setup: 'tsg aaa "d',
check: {
hints: ' [options]'
}
},
{
setup: 'tsg aaa "d d',
check: {
hints: ' [options]'
}
},
{
setup: 'tsg aaa "d d"',
check: {
hints: ' [options]'
}
},
{
setup: 'tsn ex ',
check: {
hints: ''
}
},
{
setup: 'selarr',
check: {
hints: ' -> tselarr'
}
},
{
setup: 'tselar 1',
check: {
hints: ''
}
},
{
name: 'tselar |1',
setup: function() {
helpers.setInput(options, 'tselar 1', 7);
},
check: {
hints: ''
}
},
{
name: 'tselar| 1',
setup: function() {
helpers.setInput(options, 'tselar 1', 6);
},
check: {
hints: ' -> tselarr'
}
},
{
name: 'tsela|r 1',
setup: function() {
helpers.setInput(options, 'tselar 1', 5);
},
check: {
hints: ' -> tselarr'
}
},
]);
};
exports.testLong = function(options) {
helpers.setInput('tslong --sel');
helpers.check({
input: 'tslong --sel',
hints: ' <selection> <msg> [options]',
markup: 'VVVVVVVIIIII'
});
helpers.pressTab();
helpers.check({
input: 'tslong --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVIIIIIV'
});
helpers.setInput('tslong --sel ');
helpers.check({
input: 'tslong --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVIIIIIV'
});
helpers.setInput('tslong --sel s');
helpers.check({
input: 'tslong --sel s',
hints: 'pace <msg> [options]',
markup: 'VVVVVVVIIIIIVI'
});
helpers.setInput('tslong --num ');
helpers.check({
input: 'tslong --num ',
hints: '<number> <msg> [options]',
markup: 'VVVVVVVIIIIIV'
});
helpers.setInput('tslong --num 42');
helpers.check({
input: 'tslong --num 42',
hints: ' <msg> [options]',
markup: 'VVVVVVVVVVVVVVV'
});
helpers.setInput('tslong --num 42 ');
helpers.check({
input: 'tslong --num 42 ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVV'
});
helpers.setInput('tslong --num 42 --se');
helpers.check({
input: 'tslong --num 42 --se',
hints: 'l <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIII'
});
helpers.pressTab();
helpers.check({
input: 'tslong --num 42 --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIIIIV'
});
helpers.pressTab();
helpers.check({
input: 'tslong --num 42 --sel space ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
});
helpers.setInput('tslong --num 42 --sel ');
helpers.check({
input: 'tslong --num 42 --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIIIIV'
});
helpers.setInput('tslong --num 42 --sel space ');
helpers.check({
input: 'tslong --num 42 --sel space ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
});
return helpers.audit(options, [
{
setup: 'tslong --sel',
check: {
input: 'tslong --sel',
hints: ' <selection> <msg> [options]',
markup: 'VVVVVVVIIIII'
}
},
{
setup: 'tslong --sel<TAB>',
check: {
input: 'tslong --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVIIIIIV'
}
},
{
setup: 'tslong --sel ',
check: {
input: 'tslong --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVIIIIIV'
}
},
{
setup: 'tslong --sel s',
check: {
input: 'tslong --sel s',
hints: 'pace <msg> [options]',
markup: 'VVVVVVVIIIIIVI'
}
},
{
setup: 'tslong --num ',
check: {
input: 'tslong --num ',
hints: '<number> <msg> [options]',
markup: 'VVVVVVVIIIIIV'
}
},
{
setup: 'tslong --num 42',
check: {
input: 'tslong --num 42',
hints: ' <msg> [options]',
markup: 'VVVVVVVVVVVVVVV'
}
},
{
setup: 'tslong --num 42 ',
check: {
input: 'tslong --num 42 ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVV'
}
},
{
setup: 'tslong --num 42 --se',
check: {
input: 'tslong --num 42 --se',
hints: 'l <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIII'
}
},
{
skipIf: options.isJsdom,
setup: 'tslong --num 42 --se<TAB>',
check: {
input: 'tslong --num 42 --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIIIIV'
}
},
{
skipIf: options.isJsdom,
setup: 'tslong --num 42 --se<TAB><TAB>',
check: {
input: 'tslong --num 42 --sel space ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
}
},
{
setup: 'tslong --num 42 --sel ',
check: {
input: 'tslong --num 42 --sel ',
hints: 'space <msg> [options]',
markup: 'VVVVVVVVVVVVVVVVIIIIIV'
}
},
{
setup: 'tslong --num 42 --sel space ',
check: {
input: 'tslong --num 42 --sel space ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV'
}
}
]);
};
exports.testNoTab = function(options) {
helpers.setInput('tss');
helpers.pressTab();
helpers.check({
input: 'tss ',
markup: 'VVVV',
hints: ''
});
helpers.pressTab();
helpers.check({
input: 'tss ',
markup: 'VVVV',
hints: ''
});
helpers.setInput('xxxx');
helpers.check({
input: 'xxxx',
markup: 'EEEE',
hints: ''
});
helpers.pressTab();
helpers.check({
input: 'xxxx',
markup: 'EEEE',
hints: ''
});
return helpers.audit(options, [
{
setup: 'tss<TAB>',
check: {
input: 'tss ',
markup: 'VVVV',
hints: ''
}
},
{
setup: 'tss<TAB><TAB>',
check: {
input: 'tss ',
markup: 'VVVV',
hints: ''
}
},
{
setup: 'xxxx',
check: {
input: 'xxxx',
markup: 'EEEE',
hints: ''
}
},
{
name: '<TAB>',
setup: function() {
// Doing it this way avoids clearing the input buffer
return helpers.pressTab(options);
},
check: {
input: 'xxxx',
markup: 'EEEE',
hints: ''
}
}
]);
};
exports.testOutstanding = function(options) {
// See bug 779800
/*
helpers.setInput('tsg --txt1 ddd ');
helpers.check({
input: 'tsg --txt1 ddd ',
hints: 'aaa [options]',
markup: 'VVVVVVVVVVVVVVV'
});
return helpers.audit(options, [
{
setup: 'tsg --txt1 ddd ',
check: {
input: 'tsg --txt1 ddd ',
hints: 'aaa [options]',
markup: 'VVVVVVVVVVVVVVV'
}
},
]);
*/
};
exports.testCompleteIntoOptional = function(options) {
// From bug 779816
helpers.setInput('tso ');
helpers.check({
typed: 'tso ',
hints: '[text]',
markup: 'VVVV',
status: 'VALID'
});
helpers.setInput('tso');
helpers.pressTab();
helpers.check({
typed: 'tso ',
hints: '[text]',
markup: 'VVVV',
status: 'VALID'
});
};
exports.testSpaceComplete = function(options) {
helpers.setInput('tslong --sel2 wit');
helpers.check({
input: 'tslong --sel2 wit',
hints: 'h space <msg> [options]',
markup: 'VVVVVVVIIIIIIVIII',
cursor: 17,
current: 'sel2',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tslong' },
msg: { status: 'INCOMPLETE', message: '' },
num: { status: 'VALID' },
sel: { status: 'VALID' },
bool: { value: false, status: 'VALID' },
num2: { status: 'VALID' },
bool2: { value: false, status: 'VALID' },
sel2: { arg: ' --sel2 wit', status: 'INCOMPLETE' }
}
});
helpers.pressTab();
helpers.check({
input: 'tslong --sel2 \'with space\' ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
cursor: 27,
current: 'sel2',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tslong' },
msg: { status: 'INCOMPLETE', message: '' },
num: { status: 'VALID' },
sel: { status: 'VALID' },
bool: { value: false,status: 'VALID' },
num2: { status: 'VALID' },
bool2: { value: false,status: 'VALID' },
sel2: {
value: 'with space',
arg: ' --sel2 \'with space\' ',
return helpers.audit(options, [
{
setup: 'tso ',
check: {
typed: 'tso ',
hints: '[text]',
markup: 'VVVV',
status: 'VALID'
}
},
{
setup: 'tso<TAB>',
check: {
typed: 'tso ',
hints: '[text]',
markup: 'VVVV',
status: 'VALID'
}
}
});
]);
};
exports.testSpaceComplete = function(options) {
return helpers.audit(options, [
{
setup: 'tslong --sel2 wit',
check: {
input: 'tslong --sel2 wit',
hints: 'h space <msg> [options]',
markup: 'VVVVVVVIIIIIIVIII',
cursor: 17,
current: 'sel2',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tslong' },
msg: { status: 'INCOMPLETE', message: '' },
num: { status: 'VALID' },
sel: { status: 'VALID' },
bool: { value: false, status: 'VALID' },
num2: { status: 'VALID' },
bool2: { value: false, status: 'VALID' },
sel2: { arg: ' --sel2 wit', status: 'INCOMPLETE' }
}
}
},
{
skipIf: options.isJsdom,
setup: 'tslong --sel2 wit<TAB>',
check: {
input: 'tslong --sel2 \'with space\' ',
hints: '<msg> [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
cursor: 27,
current: 'sel2',
status: 'ERROR',
tooltipState: 'true:importantFieldFlag',
args: {
command: { name: 'tslong' },
msg: { status: 'INCOMPLETE', message: '' },
num: { status: 'VALID' },
sel: { status: 'VALID' },
bool: { value: false,status: 'VALID' },
num2: { status: 'VALID' },
bool2: { value: false,status: 'VALID' },
sel2: {
value: 'with space',
arg: ' --sel2 \'with space\' ',
status: 'VALID'
}
}
}
}
]);
};

Просмотреть файл

@ -26,156 +26,26 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testExec.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
var Requisition = require('gcli/cli').Requisition;
var CommandOutputManager = require('gcli/canon').CommandOutputManager;
// var mockCommands = require('gclitest/mockCommands');
var nodetype = require('gcli/types/node');
// var helpers = require('gclitest/helpers');
// var assert = require('test/assert');
var actualExec;
var actualOutput;
var hideExec = false;
var skip = 'skip';
var environment = { value: 'example environment data' };
var commandOutputManager = new CommandOutputManager();
var requisition = new Requisition(environment, null, commandOutputManager);
exports.setup = function(options) {
mockCommands.setup();
mockCommands.onCommandExec.add(commandExeced);
commandOutputManager.onOutput.add(commandOutputed);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
mockCommands.onCommandExec.remove(commandExeced);
commandOutputManager.onOutput.remove(commandOutputed);
};
function commandExeced(ev) {
actualExec = ev;
}
function commandOutputed(ev) {
actualOutput = ev.output;
}
function exec(command, expectedArgs) {
var outputObject = requisition.exec({ typed: command, hidden: hideExec });
assert.is(command.indexOf(actualExec.command.name), 0, 'Command name: ' + command);
assert.is(command, outputObject.typed, 'outputObject.command for: ' + command);
assert.ok(outputObject.completed, 'outputObject.completed false for: ' + command);
if (expectedArgs == null) {
assert.ok(false, 'expectedArgs == null for ' + command);
return;
}
if (actualExec.args == null) {
assert.ok(false, 'actualExec.args == null for ' + command);
return;
}
assert.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 (expectedArg === skip) {
return;
}
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
assert.ok(false, 'actual is not an array. ' + command + '/' + arg);
return;
}
assert.is(expectedArg.length, actualArg.length,
'Array length: ' + command + '/' + arg);
for (var i = 0; i < expectedArg.length; i++) {
assert.is(expectedArg[i], actualArg[i],
'Member: "' + command + '/' + arg + '/' + i);
}
}
else {
assert.is(expectedArg, actualArg, 'Command: "' + command + '" arg: ' + arg);
}
});
assert.is(environment, actualExec.context.environment, 'Environment');
if (!hideExec) {
assert.is(false, actualOutput.error, 'output error is false');
assert.is(command, actualOutput.typed, 'command is typed');
assert.ok(typeof actualOutput.canonical === 'string', 'canonical exists');
assert.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: mockCommands.option1, optionValue: '10' });
exec('tsv option2 10', { optionType: mockCommands.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, nodes: skip, nodes2: skip });
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 = {
@ -201,5 +71,575 @@ var mockDoc = {
}
};
exports.testWithHelpers = function(options) {
return helpers.audit(options, [
{
skipIf: options.isJsdom,
setup: 'tss',
check: {
input: 'tss',
hints: '',
markup: 'VVV',
cursor: 3,
current: '__command',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tss' },
}
},
exec: {
output: 'Exec: tss',
completed: true,
}
},
{
setup: 'tsv option1 10',
check: {
input: 'tsv option1 10',
hints: '',
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'optionValue',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsv' },
optionType: {
value: mockCommands.option1,
arg: ' option1',
status: 'VALID',
message: ''
},
optionValue: {
value: '10',
arg: ' 10',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsv optionType=[object Object], optionValue=10',
completed: true
}
},
{
setup: 'tsv option2 10',
check: {
input: 'tsv option2 10',
hints: '',
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'optionValue',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsv' },
optionType: {
value: mockCommands.option2,
arg: ' option2',
status: 'VALID',
message: ''
},
optionValue: {
value: 10,
arg: ' 10',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsv optionType=[object Object], optionValue=10',
completed: true
}
}
]);
};
exports.testExecText = function(options) {
return helpers.audit(options, [
{
setup: 'tsr fred',
check: {
input: 'tsr fred',
hints: '',
markup: 'VVVVVVVV',
cursor: 8,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsr' },
text: {
value: 'fred',
arg: ' fred',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsr text=fred',
completed: true,
}
},
{
setup: 'tsr fred bloggs',
check: {
input: 'tsr fred bloggs',
hints: '',
markup: 'VVVVVVVVVVVVVVV',
cursor: 15,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsr' },
text: {
value: 'fred bloggs',
arg: ' fred bloggs',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsr text=fred bloggs',
completed: true,
}
},
{
setup: 'tsr "fred bloggs"',
check: {
input: 'tsr "fred bloggs"',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
cursor: 17,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsr' },
text: {
value: 'fred bloggs',
arg: ' "fred bloggs"',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsr text=fred bloggs',
completed: true,
}
},
{
setup: 'tsr "fred bloggs',
check: {
input: 'tsr "fred bloggs',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
cursor: 16,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsr' },
text: {
value: 'fred bloggs',
arg: ' "fred bloggs',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsr text=fred bloggs',
completed: true,
}
}
]);
};
exports.testExecBoolean = function(options) {
return helpers.audit(options, [
{
setup: 'tsb',
check: {
input: 'tsb',
hints: ' [toggle]',
markup: 'VVV',
cursor: 3,
current: '__command',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsb' },
toggle: {
value: false,
arg: '',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsb toggle=false',
completed: true,
}
},
{
setup: 'tsb --toggle',
check: {
input: 'tsb --toggle',
hints: '',
markup: 'VVVVVVVVVVVV',
cursor: 12,
current: 'toggle',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
outputState: 'false:default',
args: {
command: { name: 'tsb' },
toggle: {
value: true,
arg: ' --toggle',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsb toggle=true',
completed: true,
}
}
]);
};
exports.testExecNumber = function(options) {
return helpers.audit(options, [
{
setup: 'tsu 10',
check: {
input: 'tsu 10',
hints: '',
markup: 'VVVVVV',
cursor: 6,
current: 'num',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsu' },
num: { value: 10, arg: ' 10', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsu num=10',
completed: true,
}
},
{
setup: 'tsu --num 10',
check: {
input: 'tsu --num 10',
hints: '',
markup: 'VVVVVVVVVVVV',
cursor: 12,
current: 'num',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsu' },
num: { value: 10, arg: ' --num 10', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsu num=10',
completed: true,
}
}
]);
};
exports.testExecScript = function(options) {
return helpers.audit(options, [
{
// Bug 704829 - Enable GCLI Javascript parameters
// The answer to this should be 2
setup: 'tsj { 1 + 1 }',
check: {
input: 'tsj { 1 + 1 }',
hints: '',
markup: 'VVVVVVVVVVVVV',
cursor: 13,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsj' },
javascript: {
value: '1 + 1',
arg: ' { 1 + 1 }',
status: 'VALID',
message: ''
}
}
},
exec: {
output: 'Exec: tsj javascript=1 + 1',
completed: true,
}
}
]);
};
exports.testExecNode = function(options) {
var origDoc = nodetype.getDocument();
nodetype.setDocument(mockDoc);
return helpers.audit(options, [
{
setup: 'tse :root',
check: {
input: 'tse :root',
hints: ' [options]',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'node',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tse' },
node: { value: mockBody, arg: ' :root', status: 'VALID', message: '' },
nodes: { arg: '', status: 'VALID', message: '' },
nodes2: { arg: '', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tse node=[object Object], nodes=[object Object], nodes2=[object Object]',
completed: true,
},
post: function() {
nodetype.setDocument(origDoc);
}
}
]);
};
exports.testExecSubCommand = function(options) {
return helpers.audit(options, [
{
setup: 'tsn dif fred',
check: {
input: 'tsn dif fred',
hints: '',
markup: 'VVVVVVVVVVVV',
cursor: 12,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsn dif' },
text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsnDif text=fred',
completed: true,
}
},
{
setup: 'tsn exten fred',
check: {
input: 'tsn exten fred',
hints: '',
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsn exten' },
text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsnExten text=fred',
completed: true,
}
},
{
setup: 'tsn extend fred',
check: {
input: 'tsn extend fred',
hints: '',
markup: 'VVVVVVVVVVVVVVV',
cursor: 15,
current: 'text',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsn extend' },
text: { value: 'fred', arg: ' fred', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsnExtend text=fred',
completed: true,
}
}
]);
};
exports.testExecArray = function(options) {
return helpers.audit(options, [
{
setup: 'tselarr 1',
check: {
input: 'tselarr 1',
hints: '',
markup: 'VVVVVVVVV',
cursor: 9,
current: 'num',
status: 'VALID',
predictions: ['1'],
unassigned: [ ],
outputState: 'false:default',
args: {
command: { name: 'tselarr' },
num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
arr: { /*value:,*/ arg: '{}', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tselarr num=1, arr=',
completed: true,
}
},
{
setup: 'tselarr 1 a',
check: {
input: 'tselarr 1 a',
hints: '',
markup: 'VVVVVVVVVVV',
cursor: 11,
current: 'arr',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tselarr' },
num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
arr: { /*value:a,*/ arg: '{ a}', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tselarr num=1, arr=a',
completed: true,
}
},
{
setup: 'tselarr 1 a b',
check: {
input: 'tselarr 1 a b',
hints: '',
markup: 'VVVVVVVVVVVVV',
cursor: 13,
current: 'arr',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tselarr' },
num: { value: '1', arg: ' 1', status: 'VALID', message: '' },
arr: { /*value:a,b,*/ arg: '{ a, b}', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tselarr num=1, arr=a,b',
completed: true,
}
}
]);
};
exports.testExecMultiple = function(options) {
return helpers.audit(options, [
{
setup: 'tsm a 10 10',
check: {
input: 'tsm a 10 10',
hints: '',
markup: 'VVVVVVVVVVV',
cursor: 11,
current: 'num',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: 'tsm' },
abc: { value: 'a', arg: ' a', status: 'VALID', message: '' },
txt: { value: '10', arg: ' 10', status: 'VALID', message: '' },
num: { value: 10, arg: ' 10', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsm abc=a, txt=10, num=10',
completed: true,
}
}
]);
};
exports.testExecDefaults = function(options) {
return helpers.audit(options, [
{
// Bug 707009 - GCLI doesn't always fill in default parameters properly
setup: 'tsg aaa',
check: {
input: 'tsg aaa',
hints: ' [options]',
markup: 'VVVVVVV',
cursor: 7,
current: 'solo',
status: 'VALID',
predictions: ['aaa'],
unassigned: [ ],
args: {
command: { name: 'tsg' },
solo: { value: 'aaa', arg: ' aaa', status: 'VALID', message: '' },
txt1: { value: undefined, arg: '', status: 'VALID', message: '' },
bool: { value: false, arg: '', status: 'VALID', message: '' },
txt2: { value: undefined, arg: '', status: 'VALID', message: '' },
num: { value: undefined, arg: '', status: 'VALID', message: '' },
}
},
exec: {
output: 'Exec: tsg solo=aaa, txt1=null, bool=false, txt2=d, num=42',
completed: true,
}
}
]);
};
// });

Просмотреть файл

@ -16,65 +16,64 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testFocus.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var test = require('test/assert');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function(options) {
mockCommands.setup();
helpers.setup(options);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
helpers.shutdown(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({ typed: 'help' });
helpers.setInput('tsn deep');
helpers.check({
input: 'tsn deep',
hints: '',
markup: 'IIIVIIII',
cursor: 8,
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'false:default'
});
helpers.pressReturn();
helpers.check({
input: 'tsn deep',
hints: '',
markup: 'IIIVIIII',
cursor: 8,
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'true:isError'
});
return helpers.audit(options, [
{
skipRemainingIf: options.isJsdom,
name: 'exec setup',
setup: function() {
// Just check that we've got focus, and everything is clear
helpers.focusInput(options);
return helpers.setInput(options, 'help');
},
check: { },
exec: { }
},
{
setup: 'tsn deep',
check: {
input: 'tsn deep',
hints: '',
markup: 'IIIVIIII',
cursor: 8,
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'false:default'
}
},
{
setup: 'tsn deep<TAB><RETURN>',
check: {
input: 'tsn deep ',
hints: '',
markup: 'IIIIIIIIV',
cursor: 9,
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'true:isError'
}
}
]);
};

Просмотреть файл

@ -26,30 +26,19 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testHistory.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var History = require('gcli/history').History;
exports.setup = function() {
};
exports.shutdown = function() {
};
exports.testSimpleHistory = function () {
exports.testSimpleHistory = function (options) {
var history = new History({});
history.add('foo');
history.add('bar');
@ -63,7 +52,7 @@ exports.testSimpleHistory = function () {
assert.is('foo', history.backward());
};
exports.testBackwardsPastIndex = function () {
exports.testBackwardsPastIndex = function (options) {
var history = new History({});
history.add('foo');
history.add('bar');
@ -75,7 +64,7 @@ exports.testBackwardsPastIndex = function () {
assert.is('foo', history.backward());
};
exports.testForwardsPastIndex = function () {
exports.testForwardsPastIndex = function (options) {
var history = new History({});
history.add('foo');
history.add('bar');

Просмотреть файл

@ -16,344 +16,383 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIncomplete.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function(options) {
mockCommands.setup();
helpers.setup(options);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
helpers.shutdown(options);
};
exports.testBasic = function(options) {
var requisition = options.display.requisition;
return helpers.audit(options, [
{
setup: 'tsu 2 extra',
check: {
args: {
num: { value: 2, type: 'Argument' }
}
},
post: function() {
var requisition = options.display.requisition;
helpers.setInput('tsu 2 extra');
helpers.check({
args: {
num: { value: 2, type: 'Argument' }
}
});
assert.is(requisition._unassigned.length, 1, 'single unassigned: tsu 2 extra');
assert.is(requisition._unassigned[0].param.type.isIncompleteName, false,
'unassigned.isIncompleteName: tsu 2 extra');
helpers.setInput('tsu');
helpers.check({
args: {
num: { value: undefined, type: 'BlankArgument' }
}
});
helpers.setInput('tsg');
helpers.check({
args: {
solo: { type: 'BlankArgument' },
txt1: { type: 'BlankArgument' },
bool: { type: 'BlankArgument' },
txt2: { type: 'BlankArgument' },
num: { type: 'BlankArgument' }
}
});
assert.is(requisition._unassigned.length,
1,
'single unassigned: tsu 2 extra');
assert.is(requisition._unassigned[0].param.type.isIncompleteName,
false,
'unassigned.isIncompleteName: tsu 2 extra');
}
},
{
setup: 'tsu',
check: {
args: {
num: { value: undefined, type: 'BlankArgument' }
}
}
},
{
setup: 'tsg',
check: {
args: {
solo: { type: 'BlankArgument' },
txt1: { type: 'BlankArgument' },
bool: { type: 'BlankArgument' },
txt2: { type: 'BlankArgument' },
num: { type: 'BlankArgument' }
}
}
},
]);
};
exports.testCompleted = function(options) {
helpers.setInput('tsela');
helpers.pressTab();
helpers.check({
args: {
command: { name: 'tselarr', type: 'Argument' },
num: { type: 'BlankArgument' },
arr: { type: 'ArrayArgument' },
return helpers.audit(options, [
{
setup: 'tsela<TAB>',
check: {
args: {
command: { name: 'tselarr', type: 'Argument' },
num: { type: 'BlankArgument' },
arr: { type: 'ArrayArgument' }
}
}
},
{
setup: 'tsn dif ',
check: {
input: 'tsn dif ',
hints: '<text>',
markup: 'VVVVVVVV',
cursor: 8,
status: 'ERROR',
args: {
command: { name: 'tsn dif', type: 'MergedArgument' },
text: { type: 'BlankArgument', status: 'INCOMPLETE' }
}
}
},
{
setup: 'tsn di<TAB>',
check: {
input: 'tsn dif ',
hints: '<text>',
markup: 'VVVVVVVV',
cursor: 8,
status: 'ERROR',
args: {
command: { name: 'tsn dif', type: 'Argument' },
text: { type: 'BlankArgument', status: 'INCOMPLETE' }
}
}
},
// The above 2 tests take different routes to 'tsn dif '.
// The results should be similar. The difference is in args.command.type.
{
setup: 'tsg -',
check: {
input: 'tsg -',
hints: '-txt1 <solo> [options]',
markup: 'VVVVI',
cursor: 5,
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
}
},
{
skipIf: options.isJsdom,
setup: 'tsg -<TAB>',
check: {
input: 'tsg --txt1 ',
hints: '<string> <solo> [options]',
markup: 'VVVVIIIIIIV',
cursor: 11,
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'INCOMPLETE' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
}
},
{
setup: 'tsg --txt1 fred',
check: {
input: 'tsg --txt1 fred',
hints: ' <solo> [options]',
markup: 'VVVVVVVVVVVVVVV',
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: 'fred', status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
}
},
{
setup: 'tscook key value --path path --',
check: {
input: 'tscook key value --path path --',
hints: 'domain [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVII',
status: 'ERROR',
args: {
key: { value: 'key', status: 'VALID' },
value: { value: 'value', status: 'VALID' },
path: { value: 'path', status: 'VALID' },
domain: { value: undefined, status: 'VALID' },
secure: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tscook key value --path path --domain domain --',
check: {
input: 'tscook key value --path path --domain domain --',
hints: 'secure [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVII',
status: 'ERROR',
args: {
key: { value: 'key', status: 'VALID' },
value: { value: 'value', status: 'VALID' },
path: { value: 'path', status: 'VALID' },
domain: { value: 'domain', status: 'VALID' },
secure: { value: false, status: 'VALID' }
}
}
}
});
]);
helpers.setInput('tsn dif ');
helpers.check({
input: 'tsn dif ',
hints: '<text>',
markup: 'VVVVVVVV',
cursor: 8,
status: 'ERROR',
args: {
command: { name: 'tsn dif', type: 'MergedArgument' },
text: { type: 'BlankArgument', status: 'INCOMPLETE' }
}
});
helpers.setInput('tsn di');
helpers.pressTab();
helpers.check({
input: 'tsn dif ',
hints: '<text>',
markup: 'VVVVVVVV',
cursor: 8,
status: 'ERROR',
args: {
command: { name: 'tsn dif', type: 'Argument' },
text: { type: 'BlankArgument', status: 'INCOMPLETE' }
}
});
// The above 2 tests take different routes to 'tsn dif '. The results should
// be similar. The difference is in args.command.type.
helpers.setInput('tsg -');
helpers.check({
input: 'tsg -',
hints: '-txt1 <solo> [options]',
markup: 'VVVVI',
cursor: 5,
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
});
helpers.pressTab();
helpers.check({
input: 'tsg --txt1 ',
hints: '<string> <solo> [options]',
markup: 'VVVVIIIIIIV',
cursor: 11,
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'INCOMPLETE' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
});
helpers.setInput('tsg --txt1 fred');
helpers.check({
input: 'tsg --txt1 fred',
hints: ' <solo> [options]',
markup: 'VVVVVVVVVVVVVVV',
status: 'ERROR',
args: {
solo: { value: undefined, status: 'INCOMPLETE' },
txt1: { value: 'fred', status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
});
helpers.setInput('tscook key value --path path --');
helpers.check({
input: 'tscook key value --path path --',
hints: 'domain [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVII',
status: 'ERROR',
args: {
key: { value: 'key', status: 'VALID' },
value: { value: 'value', status: 'VALID' },
path: { value: 'path', status: 'VALID' },
domain: { value: undefined, status: 'VALID' },
secure: { value: false, status: 'VALID' }
}
});
helpers.setInput('tscook key value --path path --domain domain --');
helpers.check({
input: 'tscook key value --path path --domain domain --',
hints: 'secure [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVII',
status: 'ERROR',
args: {
key: { value: 'key', status: 'VALID' },
value: { value: 'value', status: 'VALID' },
path: { value: 'path', status: 'VALID' },
domain: { value: 'domain', status: 'VALID' },
secure: { value: false, status: 'VALID' }
}
});
};
exports.testCase = function(options) {
helpers.setInput('tsg AA');
helpers.check({
input: 'tsg AA',
hints: ' [options] -> aaa',
markup: 'VVVVII',
status: 'ERROR',
args: {
solo: { value: undefined, text: 'AA', status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
});
return helpers.audit(options, [
{
setup: 'tsg AA',
check: {
input: 'tsg AA',
hints: ' [options] -> aaa',
markup: 'VVVVII',
status: 'ERROR',
args: {
solo: { value: undefined, text: 'AA', status: 'INCOMPLETE' },
txt1: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
txt2: { value: undefined, status: 'VALID' },
num: { value: undefined, status: 'VALID' }
}
}
},
]);
};
exports.testIncomplete = function(options) {
var requisition = options.display.requisition;
return helpers.audit(options, [
{
setup: 'tsm a a -',
check: {
args: {
abc: { value: 'a', type: 'Argument' },
txt: { value: 'a', type: 'Argument' },
num: { value: undefined, arg: ' -', type: 'Argument', status: 'INCOMPLETE' }
}
}
},
{
setup: 'tsg -',
check: {
args: {
solo: { type: 'BlankArgument' },
txt1: { type: 'BlankArgument' },
bool: { type: 'BlankArgument' },
txt2: { type: 'BlankArgument' },
num: { type: 'BlankArgument' }
}
},
post: function() {
var requisition = options.display.requisition;
helpers.setInput('tsm a a -');
helpers.check({
args: {
abc: { value: 'a', type: 'Argument' },
txt: { value: 'a', type: 'Argument' },
num: { value: undefined, arg: ' -', type: 'Argument', status: 'INCOMPLETE' }
}
});
helpers.setInput('tsg -');
helpers.check({
args: {
solo: { type: 'BlankArgument' },
txt1: { type: 'BlankArgument' },
bool: { type: 'BlankArgument' },
txt2: { type: 'BlankArgument' },
num: { type: 'BlankArgument' }
}
});
assert.is(requisition._unassigned[0], requisition.getAssignmentAt(5),
'unassigned -');
assert.is(requisition._unassigned.length, 1, 'single unassigned - tsg -');
assert.is(requisition._unassigned[0].param.type.isIncompleteName, true,
'unassigned.isIncompleteName: tsg -');
assert.is(requisition._unassigned[0],
requisition.getAssignmentAt(5),
'unassigned -');
assert.is(requisition._unassigned.length,
1,
'single unassigned - tsg -');
assert.is(requisition._unassigned[0].param.type.isIncompleteName,
true,
'unassigned.isIncompleteName: tsg -');
}
},
]);
};
exports.testHidden = function(options) {
helpers.setInput('tshidde');
helpers.check({
input: 'tshidde',
hints: ' -> tse',
status: 'ERROR'
});
helpers.setInput('tshidden');
helpers.check({
input: 'tshidden',
hints: ' [options]',
markup: 'VVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --vis');
helpers.check({
input: 'tshidden --vis',
hints: 'ible [options]',
markup: 'VVVVVVVVVIIIII',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --invisiblestrin');
helpers.check({
input: 'tshidden --invisiblestrin',
hints: ' [options]',
markup: 'VVVVVVVVVEEEEEEEEEEEEEEEE',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --invisiblestring');
helpers.check({
input: 'tshidden --invisiblestring',
hints: ' <string> [options]',
markup: 'VVVVVVVVVIIIIIIIIIIIIIIIII',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'INCOMPLETE' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --invisiblestring x');
helpers.check({
input: 'tshidden --invisiblestring x',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: 'x', status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --invisibleboolea');
helpers.check({
input: 'tshidden --invisibleboolea',
hints: ' [options]',
markup: 'VVVVVVVVVEEEEEEEEEEEEEEEEE',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
helpers.setInput('tshidden --invisibleboolean');
helpers.check({
input: 'tshidden --invisibleboolean',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: true, status: 'VALID' }
}
});
helpers.setInput('tshidden --visible xxx');
helpers.check({
input: 'tshidden --visible xxx',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
hints: '',
args: {
visible: { value: 'xxx', status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
});
return helpers.audit(options, [
{
setup: 'tshidde',
check: {
input: 'tshidde',
hints: ' -> tse',
status: 'ERROR'
}
},
{
setup: 'tshidden',
check: {
input: 'tshidden',
hints: ' [options]',
markup: 'VVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --vis',
check: {
input: 'tshidden --vis',
hints: 'ible [options]',
markup: 'VVVVVVVVVIIIII',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --invisiblestrin',
check: {
input: 'tshidden --invisiblestrin',
hints: ' [options]',
markup: 'VVVVVVVVVEEEEEEEEEEEEEEEE',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --invisiblestring',
check: {
input: 'tshidden --invisiblestring',
hints: ' <string> [options]',
markup: 'VVVVVVVVVIIIIIIIIIIIIIIIII',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'INCOMPLETE' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --invisiblestring x',
check: {
input: 'tshidden --invisiblestring x',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: 'x', status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --invisibleboolea',
check: {
input: 'tshidden --invisibleboolea',
hints: ' [options]',
markup: 'VVVVVVVVVEEEEEEEEEEEEEEEEE',
status: 'ERROR',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
{
setup: 'tshidden --invisibleboolean',
check: {
input: 'tshidden --invisibleboolean',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
visible: { value: undefined, status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: true, status: 'VALID' }
}
}
},
{
setup: 'tshidden --visible xxx',
check: {
input: 'tshidden --visible xxx',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
hints: '',
args: {
visible: { value: 'xxx', status: 'VALID' },
invisiblestring: { value: undefined, status: 'VALID' },
invisibleboolean: { value: false, status: 'VALID' }
}
}
},
]);
};
// });

Просмотреть файл

@ -26,25 +26,18 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testInputter.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var mockCommands = require('gclitest/mockCommands');
var KeyEvent = require('gcli/util').KeyEvent;
var KeyEvent = require('util/util').KeyEvent;
// var assert = require('test/assert');
// var mockCommands = require('gclitest/mockCommands');
var latestEvent = undefined;
var latestOutput = undefined;
@ -65,9 +58,10 @@ var outputted = function(ev) {
ev.output.onChange.add(updateData);
};
exports.setup = function(options) {
options.display.requisition.commandOutputManager.onOutput.add(outputted);
mockCommands.setup();
options.display.requisition.commandOutputManager.onOutput.add(outputted);
};
exports.shutdown = function(options) {
@ -85,39 +79,36 @@ exports.testOutput = function(options) {
inputter.setInput('tss');
inputter.onKeyDown({
keyCode: KeyEvent.DOM_VK_RETURN
});
var ev0 = { keyCode: KeyEvent.DOM_VK_RETURN };
inputter.onKeyDown(ev0);
assert.is(inputter.element.value, 'tss', 'inputter should do nothing on RETURN keyDown');
assert.is(latestEvent, undefined, 'no events this test');
assert.is(latestData, undefined, 'no data this test');
inputter.onKeyUp({
keyCode: KeyEvent.DOM_VK_RETURN
var ev1 = { keyCode: KeyEvent.DOM_VK_RETURN };
return inputter.handleKeyUp(ev1).then(function() {
assert.ok(latestEvent != null, 'events this test');
assert.is(latestData, 'Exec: tss ', 'last command is tss');
assert.is(inputter.element.value, '', 'inputter should exec on RETURN keyUp');
assert.ok(focusManager._recentOutput, 'recent output happened');
var ev2 = { keyCode: KeyEvent.DOM_VK_F1 };
return inputter.handleKeyUp(ev2).then(function() {
assert.ok(!focusManager._recentOutput, 'no recent output happened post F1');
assert.ok(focusManager._helpRequested, 'F1 = help');
var ev3 = { keyCode: KeyEvent.DOM_VK_ESCAPE };
return inputter.handleKeyUp(ev3).then(function() {
assert.ok(!focusManager._helpRequested, 'ESCAPE = anti help');
latestOutput.onClose();
});
});
});
assert.ok(latestEvent != null, 'events this test');
assert.is(latestData.command.name, 'tss', 'last command is tss');
assert.is(inputter.element.value, '', 'inputter should exec on RETURN keyUp');
assert.ok(focusManager._recentOutput, 'recent output happened');
inputter.onKeyUp({
keyCode: KeyEvent.DOM_VK_F1
});
assert.ok(!focusManager._recentOutput, 'no recent output happened post F1');
assert.ok(focusManager._helpRequested, 'F1 = help');
inputter.onKeyUp({
keyCode: KeyEvent.DOM_VK_ESCAPE
});
assert.ok(!focusManager._helpRequested, 'ESCAPE = anti help');
latestOutput.onClose();
};

Просмотреть файл

@ -26,71 +26,60 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testIntro.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
// var helpers = require('gclitest/helpers');
// var assert = require('test/assert');
var canon = require('gcli/canon');
'use strict';
exports.setup = function(options) {
helpers.setup(options);
};
// var helpers = require('gclitest/helpers');
var canon = require('gcli/canon');
exports.shutdown = function(options) {
helpers.shutdown(options);
};
exports.testIntroStatus = function(options) {
if (canon.getCommand('intro') == null) {
assert.log('Skipping testIntroStatus; missing intro command.');
return;
exports.testIntroStatus = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: function commandIntroMissing() {
return canon.getCommand('intro') == null;
},
setup: 'intro',
check: {
typed: 'intro',
markup: 'VVVVV',
status: 'VALID',
hints: ''
}
},
{
setup: 'intro foo',
check: {
typed: 'intro foo',
markup: 'VVVVVVEEE',
status: 'ERROR',
hints: ''
}
},
{
setup: 'intro',
check: {
typed: 'intro',
markup: 'VVVVV',
status: 'VALID',
hints: ''
},
exec: {
output: [
/command\s*line/,
/help/,
/F1/,
/Escape/
]
}
}
]);
};
helpers.setInput('intro');
helpers.check({
typed: 'intro',
markup: 'VVVVV',
status: 'VALID',
hints: ''
});
helpers.setInput('intro foo');
helpers.check({
typed: 'intro foo',
markup: 'VVVVVVEEE',
status: 'ERROR',
hints: ''
});
};
exports.testIntroExec = function(options) {
if (canon.getCommand('intro') == null) {
assert.log('Skipping testIntroStatus; missing intro command.');
return;
}
helpers.exec({
typed: 'intro',
args: { },
outputMatch: [
/command\s*line/,
/help/,
/F1/,
/Escape/
]
});
};
// });

Просмотреть файл

@ -26,41 +26,24 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testJs.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
var Requisition = require('gcli/cli').Requisition;
var Status = require('gcli/types').Status;
// var assert = require('test/assert');
// var helpers = require('gclitest/helpers');
var javascript = require('gcli/types/javascript');
var canon = require('gcli/canon');
// var assert = require('test/assert');
var debug = false;
var requ;
var assign;
var status;
var statuses;
var tempWindow;
var tempWindow = undefined;
exports.setup = function(options) {
tempWindow = javascript.getGlobalObject();
javascript.setGlobalObject(options.window);
Object.defineProperty(options.window, 'donteval', {
get: function() {
assert.ok(false, 'donteval should not be used');
@ -69,142 +52,423 @@ exports.setup = function(options) {
enumerable: true,
configurable : true
});
javascript.setGlobalObject(options.window);
};
exports.shutdown = function(options) {
delete options.window.donteval;
javascript.setGlobalObject(tempWindow);
tempWindow = undefined;
delete options.window.donteval;
};
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) {
assert.is('{', requ.commandAssignment.value.name, 'is exec');
assert.is(expStatuses, statuses, 'unexpected status markup');
assert.is(expStatus.toString(), status.toString(), 'unexpected status');
assert.is(expAssign, assign.value, 'unexpected assignment');
if (expPredict != null) {
var contains;
if (Array.isArray(expPredict)) {
expPredict.forEach(function(p) {
contains = predictionsHas(p);
assert.ok(contains, 'missing prediction ' + p);
});
}
else if (typeof expPredict === 'number') {
contains = true;
assert.is(assign.getPredictions().length, expPredict, 'prediction count');
if (assign.getPredictions().length !== expPredict) {
assign.getPredictions().forEach(function(prediction) {
assert.log('actual prediction: ', prediction);
});
exports.testBasic = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: function commandJsMissing() {
return canon.getCommand('{') == null;
},
setup: '{',
check: {
input: '{',
hints: '',
markup: 'V',
cursor: 1,
current: 'javascript',
status: 'ERROR',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: undefined,
arg: '{',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ ',
check: {
input: '{ ',
hints: '',
markup: 'VV',
cursor: 2,
current: 'javascript',
status: 'ERROR',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: undefined,
arg: '{ ',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ w',
check: {
input: '{ w',
hints: 'indow',
markup: 'VVI',
cursor: 3,
current: 'javascript',
status: 'ERROR',
predictionsContains: [ 'window' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'w',
arg: '{ w',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ windo',
check: {
input: '{ windo',
hints: 'w',
markup: 'VVIIIII',
cursor: 7,
current: 'javascript',
status: 'ERROR',
predictions: [ 'window' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'windo',
arg: '{ windo',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ window',
check: {
input: '{ window',
hints: '',
markup: 'VVVVVVVV',
cursor: 8,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'window',
arg: '{ window',
status: 'VALID',
message: ''
}
}
}
},
{
setup: '{ window.do',
check: {
input: '{ window.do',
hints: 'cument',
markup: 'VVIIIIIIIII',
cursor: 11,
current: 'javascript',
status: 'ERROR',
predictionsContains: [ 'window.document' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'window.do',
arg: '{ window.do',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ window.document.title',
check: {
input: '{ window.document.title',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVV',
cursor: 23,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'window.document.title',
arg: '{ window.document.title',
status: 'VALID',
message: ''
}
}
}
}
else {
contains = predictionsHas(expPredict);
assert.ok(contains, 'missing prediction ' + expPredict);
]);
};
exports.testDocument = function(options) {
return helpers.audit(options, [
{
skipRemainingIf: function commandJsMissing() {
return canon.getCommand('{') == null;
},
setup: '{ docu',
check: {
input: '{ docu',
hints: 'ment',
markup: 'VVIIII',
cursor: 6,
current: 'javascript',
status: 'ERROR',
predictions: [ 'document' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'docu',
arg: '{ docu',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ docu<TAB>',
check: {
input: '{ document',
hints: '',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'document',
arg: '{ document',
status: 'VALID',
message: ''
}
}
}
},
{
setup: '{ document.titl',
check: {
input: '{ document.titl',
hints: 'e',
markup: 'VVIIIIIIIIIIIII',
cursor: 15,
current: 'javascript',
status: 'ERROR',
predictions: [ 'document.title' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'document.titl',
arg: '{ document.titl',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
skipIf: options.isJsdom,
setup: '{ document.titl<TAB>',
check: {
input: '{ document.title ',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
cursor: 17,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'document.title',
arg: '{ document.title ',
status: 'VALID',
message: ''
}
}
}
},
{
setup: '{ document.title',
check: {
input: '{ document.title',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
cursor: 16,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'document.title',
arg: '{ document.title',
status: 'VALID',
message: ''
}
}
}
}
]);
};
if (!contains) {
assert.log('Predictions: ' + assign.getPredictions().map(function(p) {
return p.name;
}).join(', '));
}
}
}
exports.testBasic = function(options) {
if (!canon.getCommand('{')) {
assert.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);
exports.testDonteval = function(options) {
if (!options.isJsdom) {
// jsdom causes an eval here, maybe that's node/v8?
assert.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);
return helpers.audit(options, [
{
skipRemainingIf: function commandJsMissing() {
return canon.getCommand('{') == null;
},
setup: '{ don',
check: {
input: '{ don',
hints: 'teval',
markup: 'VVIII',
cursor: 5,
current: 'javascript',
status: 'ERROR',
predictions: [ 'donteval' ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'don',
arg: '{ don',
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: '{ donteval',
check: {
input: '{ donteval',
hints: '',
markup: 'VVVVVVVVVV',
cursor: 10,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'donteval',
arg: '{ donteval',
status: 'VALID',
message: ''
}
}
}
},
/*
// 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
{
setup: '{ donteval.',
check: {
input: '{ donteval.',
hints: '',
markup: 'VVVVVVVVVVV',
cursor: 11,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'donteval.',
arg: '{ donteval.',
status: 'VALID',
message: ''
}
}
}
},
*/
{
setup: '{ donteval.cant',
check: {
input: '{ donteval.cant',
hints: '',
markup: 'VVVVVVVVVVVVVVV',
cursor: 15,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'donteval.cant',
arg: '{ donteval.cant',
status: 'VALID',
message: ''
}
}
}
},
{
setup: '{ donteval.xxx',
check: {
input: '{ donteval.xxx',
hints: '',
markup: 'VVVVVVVVVVVVVV',
cursor: 14,
current: 'javascript',
status: 'VALID',
predictions: [ ],
unassigned: [ ],
args: {
command: { name: '{' },
javascript: {
value: 'donteval.xxx',
arg: '{ donteval.xxx',
status: 'VALID',
message: ''
}
}
}
}
]);
};

Просмотреть файл

@ -26,218 +26,490 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testKeyboard.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
var Requisition = require('gcli/cli').Requisition;
var canon = require('gcli/canon');
// var mockCommands = require('gclitest/mockCommands');
var javascript = require('gcli/types/javascript');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
var canon = require('gcli/canon');
// var assert = require('test/assert');
var tempWindow;
var inputter;
var tempWindow = undefined;
exports.setup = function(options) {
mockCommands.setup();
tempWindow = javascript.getGlobalObject();
javascript.setGlobalObject(options.window);
if (options.display) {
inputter = options.display.inputter;
}
mockCommands.setup();
};
exports.shutdown = function(options) {
mockCommands.shutdown();
inputter = undefined;
javascript.setGlobalObject(tempWindow);
tempWindow = undefined;
mockCommands.shutdown();
};
var COMPLETES_TO = 'complete';
var KEY_UPS_TO = 'keyup';
var KEY_DOWNS_TO = 'keydown';
// Bug 664377: Add tests for internal completion. i.e. "tsela<TAB> 1"
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:
requisition.increment(assignment);
break;
case KEY_DOWNS_TO:
requisition.decrement(assignment);
break;
}
assert.is(after, requisition.toString(),
initial + ' + ' + action + ' -> ' + after);
if (expectedCursor != null) {
if (inputter) {
assert.is(expectedCursor, inputter.getInputState().cursor.start,
'Ending cursor position for \'' + initial + '\'');
exports.testSimple = function(options) {
return helpers.audit(options, [
{
setup: 'tsela<TAB>',
check: { input: 'tselarr ', cursor: 8 }
},
{
setup: 'tsn di<TAB>',
check: { input: 'tsn dif ', cursor: 8 }
},
{
setup: 'tsg a<TAB>',
check: { input: 'tsg aaa ', cursor: 8 }
}
}
}
]);
};
exports.testComplete = function(options) {
if (!inputter) {
assert.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('{')) {
assert.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 jsdom
if (!options.isJsdom) {
check('{ window.document.titl', COMPLETES_TO, '{ window.document.title ', 0);
return helpers.audit(options, [
{
setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><DOWN><TAB>',
check: { input: 'tsn exte ' }
},
{
setup: 'tsn e<DOWN><DOWN><DOWN><DOWN><TAB>',
check: { input: 'tsn ext ' }
},
{
setup: 'tsn e<DOWN><DOWN><DOWN><TAB>',
check: { input: 'tsn extend ' }
},
{
setup: 'tsn e<DOWN><DOWN><TAB>',
check: { input: 'tsn exten ' }
},
{
setup: 'tsn e<DOWN><TAB>',
check: { input: 'tsn exte ' }
},
{
setup: 'tsn e<TAB>',
check: { input: 'tsn ext ' }
},
{
setup: 'tsn e<UP><TAB>',
check: { input: 'tsn extend ' }
},
{
setup: 'tsn e<UP><UP><TAB>',
check: { input: 'tsn exten ' }
},
{
setup: 'tsn e<UP><UP><UP><TAB>',
check: { input: 'tsn exte ' }
},
{
setup: 'tsn e<UP><UP><UP><UP><TAB>',
check: { input: 'tsn ext ' }
},
{
setup: 'tsn e<UP><UP><UP><UP><UP><TAB>',
check: { input: 'tsn extend ' }
},
{
setup: 'tsn e<UP><UP><UP><UP><UP><UP><TAB>',
check: { input: 'tsn exten ' }
},
{
setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><TAB>',
check: { input: 'tsn exte ' }
},
{
setup: 'tsn e<UP><UP><UP><UP><UP><UP><UP><UP><TAB>',
check: { input: 'tsn ext ' }
}
else {
assert.log('Skipping tests due to jsdom and bug 717228.');
}
}
]);
};
exports.testInternalComplete = function(options) {
// Bug 664377
// check('tsela 1', COMPLETES_TO, 'tselarr 1', 0, 3, 8);
exports.testScript = function(options) {
return helpers.audit(options, [
{
skipIf: function commandJsMissing() {
return canon.getCommand('{') == null;
},
setup: '{ wind<TAB>',
check: { input: '{ window' }
},
{
skipIf: function commandJsMissing() {
return canon.getCommand('{') == null;
},
setup: '{ window.docum<TAB>',
check: { input: '{ window.document' }
}
]);
};
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');
exports.testJsdom = function(options) {
return helpers.audit(options, [
{
skipIf: function jsDomOrCommandJsMissing() {
return options.isJsdom || canon.getCommand('{') == null;
},
setup: '{ window.document.titl<TAB>',
check: { input: '{ window.document.title ' }
}
]);
};
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');
exports.testIncr = function(options) {
return helpers.audit(options, [
/*
// We currently refuse to increment/decrement things with a non-valid
// status which makes sense for many cases, and is a decent default.
// However in theory we could do better, these tests are there for then
{
setup: 'tsu -70<UP>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -7<UP>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -6<UP>',
check: { input: 'tsu -5' }
},
*/
{
setup: 'tsu -5<UP>',
check: { input: 'tsu -3' }
},
{
setup: 'tsu -4<UP>',
check: { input: 'tsu -3' }
},
{
setup: 'tsu -3<UP>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu -2<UP>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu -1<UP>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu 0<UP>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 1<UP>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 2<UP>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 3<UP>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 4<UP>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 5<UP>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 6<UP>',
check: { input: 'tsu 9' }
},
{
setup: 'tsu 7<UP>',
check: { input: 'tsu 9' }
},
{
setup: 'tsu 8<UP>',
check: { input: 'tsu 9' }
},
{
setup: 'tsu 9<UP>',
check: { input: 'tsu 10' }
},
{
setup: 'tsu 10<UP>',
check: { input: 'tsu 10' }
}
/*
// See notes above
{
setup: 'tsu 100<UP>',
check: { input: 'tsu 10' }
}
*/
]);
};
check('tsf -70', KEY_UPS_TO, 'tsf -6.5');
check('tsf -6.5', KEY_UPS_TO, 'tsf -6');
check('tsf -6', KEY_UPS_TO, 'tsf -4.5');
check('tsf -4.5', KEY_UPS_TO, 'tsf -3');
check('tsf -4', KEY_UPS_TO, 'tsf -3');
check('tsf -3', KEY_UPS_TO, 'tsf -1.5');
check('tsf -1.5', KEY_UPS_TO, 'tsf 0');
check('tsf 0', KEY_UPS_TO, 'tsf 1.5');
check('tsf 1.5', KEY_UPS_TO, 'tsf 3');
check('tsf 2', KEY_UPS_TO, 'tsf 3');
check('tsf 3', KEY_UPS_TO, 'tsf 4.5');
check('tsf 5', KEY_UPS_TO, 'tsf 6');
check('tsf 100', KEY_UPS_TO, 'tsf -6.5');
exports.testDecr = function(options) {
return helpers.audit(options, [
/*
// See notes at top of testIncr
{
setup: 'tsu -70<DOWN>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -7<DOWN>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -6<DOWN>',
check: { input: 'tsu -5' }
},
*/
{
setup: 'tsu -5<DOWN>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -4<DOWN>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -3<DOWN>',
check: { input: 'tsu -5' }
},
{
setup: 'tsu -2<DOWN>',
check: { input: 'tsu -3' }
},
{
setup: 'tsu -1<DOWN>',
check: { input: 'tsu -3' }
},
{
setup: 'tsu 0<DOWN>',
check: { input: 'tsu -3' }
},
{
setup: 'tsu 1<DOWN>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu 2<DOWN>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu 3<DOWN>',
check: { input: 'tsu 0' }
},
{
setup: 'tsu 4<DOWN>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 5<DOWN>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 6<DOWN>',
check: { input: 'tsu 3' }
},
{
setup: 'tsu 7<DOWN>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 8<DOWN>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 9<DOWN>',
check: { input: 'tsu 6' }
},
{
setup: 'tsu 10<DOWN>',
check: { input: 'tsu 9' }
}
/*
// See notes at top of testIncr
{
setup: 'tsu 100<DOWN>',
check: { input: 'tsu 9' }
}
*/
]);
};
check('tsf -70', KEY_DOWNS_TO, 'tsf 11.5');
check('tsf -6.5', KEY_DOWNS_TO, 'tsf -6.5');
check('tsf -6', KEY_DOWNS_TO, 'tsf -6.5');
check('tsf -4.5', KEY_DOWNS_TO, 'tsf -6');
check('tsf -4', KEY_DOWNS_TO, 'tsf -4.5');
check('tsf -3', KEY_DOWNS_TO, 'tsf -4.5');
check('tsf -1.5', KEY_DOWNS_TO, 'tsf -3');
check('tsf 0', KEY_DOWNS_TO, 'tsf -1.5');
check('tsf 1.5', KEY_DOWNS_TO, 'tsf 0');
check('tsf 2', KEY_DOWNS_TO, 'tsf 1.5');
check('tsf 3', KEY_DOWNS_TO, 'tsf 1.5');
check('tsf 5', KEY_DOWNS_TO, 'tsf 4.5');
check('tsf 100', KEY_DOWNS_TO, 'tsf 11.5');
exports.testIncrFloat = function(options) {
return helpers.audit(options, [
/*
// See notes at top of testIncr
{
setup: 'tsf -70<UP>',
check: { input: 'tsf -6.5' }
},
*/
{
setup: 'tsf -6.5<UP>',
check: { input: 'tsf -6' }
},
{
setup: 'tsf -6<UP>',
check: { input: 'tsf -4.5' }
},
{
setup: 'tsf -4.5<UP>',
check: { input: 'tsf -3' }
},
{
setup: 'tsf -4<UP>',
check: { input: 'tsf -3' }
},
{
setup: 'tsf -3<UP>',
check: { input: 'tsf -1.5' }
},
{
setup: 'tsf -1.5<UP>',
check: { input: 'tsf 0' }
},
{
setup: 'tsf 0<UP>',
check: { input: 'tsf 1.5' }
},
{
setup: 'tsf 1.5<UP>',
check: { input: 'tsf 3' }
},
{
setup: 'tsf 2<UP>',
check: { input: 'tsf 3' }
},
{
setup: 'tsf 3<UP>',
check: { input: 'tsf 4.5' }
},
{
setup: 'tsf 5<UP>',
check: { input: 'tsf 6' }
}
/*
// See notes at top of testIncr
{
setup: 'tsf 100<UP>',
check: { input: 'tsf -6.5' }
}
*/
]);
};
// 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');
exports.testDecrFloat = function(options) {
return helpers.audit(options, [
/*
// See notes at top of testIncr
{
setup: 'tsf -70<DOWN>',
check: { input: 'tsf 11.5' }
},
*/
{
setup: 'tsf -6.5<DOWN>',
check: { input: 'tsf -6.5' }
},
{
setup: 'tsf -6<DOWN>',
check: { input: 'tsf -6.5' }
},
{
setup: 'tsf -4.5<DOWN>',
check: { input: 'tsf -6' }
},
{
setup: 'tsf -4<DOWN>',
check: { input: 'tsf -4.5' }
},
{
setup: 'tsf -3<DOWN>',
check: { input: 'tsf -4.5' }
},
{
setup: 'tsf -1.5<DOWN>',
check: { input: 'tsf -3' }
},
{
setup: 'tsf 0<DOWN>',
check: { input: 'tsf -1.5' }
},
{
setup: 'tsf 1.5<DOWN>',
check: { input: 'tsf 0' }
},
{
setup: 'tsf 2<DOWN>',
check: { input: 'tsf 1.5' }
},
{
setup: 'tsf 3<DOWN>',
check: { input: 'tsf 1.5' }
},
{
setup: 'tsf 5<DOWN>',
check: { input: 'tsf 4.5' }
}
/*
// See notes at top of testIncr
{
setup: 'tsf 100<DOWN>',
check: { input: 'tsf 11.5' }
}
*/
]);
};
check('tselarr 3', KEY_UPS_TO, 'tselarr 2');
exports.testIncrSelection = function(options) {
/*
// Bug 829516: GCLI up/down navigation over selection is sometimes bizarre
return helpers.audit(options, [
{
setup: 'tselarr <DOWN>',
check: { hints: '2' },
exec: {}
},
{
setup: 'tselarr <DOWN><DOWN>',
check: { hints: '3' },
exec: {}
},
{
setup: 'tselarr <DOWN><DOWN><DOWN>',
check: { hints: '1' },
exec: {}
}
]);
*/
};
exports.testDecrSelection = function(options) {
/*
// Bug 829516: GCLI up/down navigation over selection is sometimes bizarre
return helpers.audit(options, [
{
setup: 'tselarr <UP>',
check: { hints: '3' }
}
]);
*/
};
// });

Просмотреть файл

@ -16,52 +16,47 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testMenu.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function(options) {
mockCommands.setup();
helpers.setup(options);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
helpers.shutdown(options);
};
exports.testOptions = function(options) {
helpers.setInput('tslong');
helpers.check({
input: 'tslong',
markup: 'VVVVVV',
status: 'ERROR',
hints: ' <msg> [options]',
args: {
msg: { value: undefined, status: 'INCOMPLETE' },
num: { value: undefined, status: 'VALID' },
sel: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
bool2: { value: false, status: 'VALID' },
sel2: { value: undefined, status: 'VALID' },
num2: { value: undefined, status: 'VALID' }
return helpers.audit(options, [
{
setup: 'tslong',
check: {
input: 'tslong',
markup: 'VVVVVV',
status: 'ERROR',
hints: ' <msg> [options]',
args: {
msg: { value: undefined, status: 'INCOMPLETE' },
num: { value: undefined, status: 'VALID' },
sel: { value: undefined, status: 'VALID' },
bool: { value: false, status: 'VALID' },
bool2: { value: false, status: 'VALID' },
sel2: { value: undefined, status: 'VALID' },
num2: { value: undefined, status: 'VALID' }
}
}
}
});
]);
};

Просмотреть файл

@ -16,293 +16,330 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testNode.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function(options) {
mockCommands.setup();
helpers.setup(options);
};
exports.shutdown = function(options) {
mockCommands.shutdown();
helpers.shutdown(options);
};
exports.testNode = function(options) {
return helpers.audit(options, [
{
setup: 'tse ',
check: {
input: 'tse ',
hints: '<node> [options]',
markup: 'VVVV',
cursor: 4,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: { status: 'INCOMPLETE', message: '' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
}
},
{
setup: 'tse :',
check: {
input: 'tse :',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
arg: ' :',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
}
},
{
setup: 'tse #',
check: {
input: 'tse #',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
}
},
{
setup: 'tse .',
check: {
input: 'tse .',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' .',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
}
},
{
skipIf: options.isJsdom,
setup: 'tse *',
check: {
input: 'tse *',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' *',
status: 'ERROR'
// message: 'Too many matches (128)'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
}
}
]);
};
exports.testNodeDom = function(options) {
var requisition = options.display.requisition;
helpers.setInput('tse ');
helpers.check({
input: 'tse ',
hints: '<node> [options]',
markup: 'VVVV',
cursor: 4,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: { status: 'INCOMPLETE', message: '' },
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse :');
helpers.check({
input: 'tse :',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
arg: ' :',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
if (options.isJsdom) {
assert.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' }
return helpers.audit(options, [
{
skipIf: options.isJsdom,
setup: 'tse :root',
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' }
},
{
skipIf: options.isJsdom,
setup: 'tse :root ',
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' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
}
});
assert.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' }
},
{
skipIf: options.isJsdom,
setup: 'tse #gcli-nomatch',
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({
input: 'tse #',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' #',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse .');
helpers.check({
input: 'tse .',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' .',
status: 'ERROR',
message: 'Syntax error in CSS query'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
helpers.setInput('tse *');
helpers.check({
input: 'tse *',
hints: ' [options]',
markup: 'VVVVE',
cursor: 5,
current: 'node',
status: 'ERROR',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: ' *',
status: 'ERROR',
// message: 'Too many matches (128)'
},
nodes: { status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
]);
};
exports.testNodes = function(options) {
var requisition = options.display.requisition;
if (options.isJsdom) {
assert.log('skipping node tests because jsdom');
return;
}
helpers.setInput('tse :root --nodes *');
helpers.check({
input: 'tse :root --nodes *',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVV',
current: 'nodes',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { arg: ' --nodes *', status: 'VALID' },
nodes2: { status: 'VALID' }
}
});
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'#gcli-input id');
helpers.setInput('tse :root --nodes2 div');
helpers.check({
input: 'tse :root --nodes2 div',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
cursor: 22,
current: 'nodes2',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { arg: ' --nodes2 div', status: 'VALID' }
}
});
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
helpers.setInput('tse --nodes ffff');
helpers.check({
input: 'tse --nodes ffff',
hints: ' <node> [options]',
markup: 'VVVVIIIIIIIVIIII',
cursor: 16,
current: 'nodes',
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'true:isError',
args: {
command: { name: 'tse' },
node: { value: undefined, arg: '', status: 'INCOMPLETE', message: '' },
nodes: { value: undefined, arg: ' --nodes ffff', status: 'INCOMPLETE', message: 'No matches' },
nodes2: { arg: '', status: 'VALID', message: '' },
}
});
/*
test.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
helpers.setInput('tse --nodes2 ffff');
helpers.check({
input: 'tse --nodes2 ffff',
hints: ' <node> [options]',
markup: 'VVVVVVVVVVVVVVVVV',
cursor: 17,
current: 'nodes2',
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'false:default',
args: {
command: { name: 'tse' },
node: { value: undefined, arg: '', status: 'INCOMPLETE', message: '' },
nodes: { arg: '', status: 'VALID', message: '' },
nodes2: { arg: ' --nodes2 ffff', status: 'VALID', message: '' },
}
});
/*
test.is(requisition.getAssignment('nodes').value.constructor.name,
'NodeList',
'#gcli-input id');
test.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
return helpers.audit(options, [
{
skipIf: options.isJsdom,
setup: 'tse :root --nodes *',
check: {
input: 'tse :root --nodes *',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVV',
current: 'nodes',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { arg: ' --nodes *', status: 'VALID' },
nodes2: { status: 'VALID' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'#gcli-input id');
}
},
{
skipIf: options.isJsdom,
setup: 'tse :root --nodes2 div',
check: {
input: 'tse :root --nodes2 div',
hints: ' [options]',
markup: 'VVVVVVVVVVVVVVVVVVVVVV',
cursor: 22,
current: 'nodes2',
status: 'VALID',
args: {
command: { name: 'tse' },
node: { arg: ' :root', status: 'VALID' },
nodes: { status: 'VALID' },
nodes2: { arg: ' --nodes2 div', status: 'VALID' }
}
},
post: function() {
assert.is(requisition.getAssignment('node').value.tagName,
'HTML',
'root id');
}
},
{
skipIf: options.isJsdom,
setup: 'tse --nodes ffff',
check: {
input: 'tse --nodes ffff',
hints: ' <node> [options]',
markup: 'VVVVIIIIIIIVIIII',
cursor: 16,
current: 'nodes',
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'true:isError',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: '',
status: 'INCOMPLETE',
message: ''
},
nodes: {
value: undefined,
arg: ' --nodes ffff',
status: 'INCOMPLETE',
message: 'No matches'
},
nodes2: { arg: '', status: 'VALID', message: '' }
}
},
post: function() {
/*
assert.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
}
},
{
skipIf: options.isJsdom,
setup: 'tse --nodes2 ffff',
check: {
input: 'tse --nodes2 ffff',
hints: ' <node> [options]',
markup: 'VVVVVVVVVVVVVVVVV',
cursor: 17,
current: 'nodes2',
status: 'ERROR',
outputState: 'false:default',
tooltipState: 'false:default',
args: {
command: { name: 'tse' },
node: {
value: undefined,
arg: '',
status: 'INCOMPLETE',
message: ''
},
nodes: { arg: '', status: 'VALID', message: '' },
nodes2: { arg: ' --nodes2 ffff', status: 'VALID', message: '' }
}
},
post: function() {
/*
assert.is(requisition.getAssignment('nodes').value.constructor.name,
'NodeList',
'#gcli-input id');
assert.is(requisition.getAssignment('nodes2').value.constructor.name,
'NodeList',
'#gcli-input id');
*/
}
},
]);
};

Просмотреть файл

@ -26,28 +26,24 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testResource.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var util = require('util/util');
var resource = require('gcli/types/resource');
var types = require('gcli/types');
var Status = require('gcli/types').Status;
// var assert = require('test/assert');
var tempDocument;
var tempDocument = undefined;
exports.setup = function(options) {
tempDocument = resource.getDocument();
@ -59,71 +55,104 @@ exports.shutdown = function(options) {
tempDocument = undefined;
};
exports.testPredictions = function(options) {
exports.testAllPredictions1 = function(options) {
if (options.isFirefox || options.isJsdom) {
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
return;
}
var resource = types.getType('resource');
return resource.getLookup().then(function(opts) {
assert.ok(opts.length > 1, 'have all resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
});
});
};
exports.testScriptPredictions = function(options) {
if (options.isFirefox || options.isJsdom) {
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
return;
}
var resource = types.getType({ name: 'resource', include: 'text/javascript' });
return resource.getLookup().then(function(opts) {
assert.ok(opts.length > 1, 'have js resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
});
});
};
exports.testStylePredictions = function(options) {
if (options.isFirefox || options.isJsdom) {
assert.log('Skipping checks due to jsdom/firefox document.stylsheets support.');
return;
}
var resource = types.getType({ name: 'resource', include: 'text/css' });
return resource.getLookup().then(function(opts) {
assert.ok(opts.length >= 1, 'have css resources');
return util.promiseEach(opts, function(prediction) {
return checkPrediction(resource, prediction);
});
});
};
exports.testAllPredictions2 = function(options) {
if (options.isJsdom) {
assert.log('Skipping checks due to jsdom document.stylsheets support.');
return;
}
var resource1 = types.getType('resource');
var options1 = resource1.getLookup();
// firefox doesn't support digging into scripts/stylesheets
if (!options.isFirefox) {
assert.ok(options1.length > 1, 'have all resources');
}
else {
assert.log('Skipping checks due to firefox document.stylsheets support.');
}
options1.forEach(function(prediction) {
checkPrediction(resource1, prediction);
var scriptRes = types.getType({ name: 'resource', include: 'text/javascript' });
return scriptRes.getLookup().then(function(scriptOptions) {
var styleRes = types.getType({ name: 'resource', include: 'text/css' });
return styleRes.getLookup().then(function(styleOptions) {
var allRes = types.getType({ name: 'resource' });
return allRes.getLookup().then(function(allOptions) {
assert.is(scriptOptions.length + styleOptions.length,
allOptions.length,
'split');
});
});
});
};
var resource2 = types.getType({ name: 'resource', include: 'text/javascript' });
var options2 = resource2.getLookup();
// firefox doesn't support digging into scripts
if (!options.isFirefox) {
assert.ok(options2.length > 1, 'have js resources');
exports.testAllPredictions3 = function(options) {
if (options.isJsdom) {
assert.log('Skipping checks due to jsdom document.stylsheets support.');
return;
}
else {
assert.log('Skipping checks due to firefox document.stylsheets support.');
}
options2.forEach(function(prediction) {
checkPrediction(resource2, prediction);
var res1 = types.getType({ name: 'resource' });
return res1.getLookup().then(function(options1) {
var res2 = types.getType('resource');
return res2.getLookup().then(function(options2) {
assert.is(options1.length, options2.length, 'type spec');
});
});
var resource3 = types.getType({ name: 'resource', include: 'text/css' });
var options3 = resource3.getLookup();
// jsdom/firefox don't support digging into stylesheets
if (!options.isJsdom && !options.isFirefox) {
assert.ok(options3.length >= 1, 'have css resources');
}
else {
assert.log('Skipping checks due to firefox document.stylsheets support.');
}
options3.forEach(function(prediction) {
checkPrediction(resource3, prediction);
});
var resource4 = types.getType({ name: 'resource' });
var options4 = resource4.getLookup();
assert.is(options1.length, options4.length, 'type spec');
assert.is(options2.length + options3.length, options4.length, 'split');
};
function checkPrediction(res, prediction) {
var name = prediction.name;
var value = prediction.value;
var conversion = res.parseString(name);
assert.is(conversion.getStatus(), Status.VALID, 'status VALID for ' + name);
assert.is(conversion.value, value, 'value for ' + name);
return res.parseString(name).then(function(conversion) {
assert.is(conversion.getStatus(), Status.VALID, 'status VALID for ' + name);
assert.is(conversion.value, value, 'value for ' + name);
var strung = res.stringify(value);
assert.is(strung, name, 'stringify for ' + name);
var strung = res.stringify(value);
assert.is(strung, name, 'stringify for ' + name);
assert.is(typeof value.loadContents, 'function', 'resource for ' + name);
assert.is(typeof value.element, 'object', 'resource for ' + name);
assert.is(typeof value.loadContents, 'function', 'resource for ' + name);
assert.is(typeof value.element, 'object', 'resource for ' + name);
});
}
// });

Просмотреть файл

@ -26,36 +26,26 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testScratchpad.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var origScratchpad;
var origScratchpad = undefined;
exports.setup = function(options) {
if (options.display) {
origScratchpad = options.display.inputter.scratchpad;
options.display.inputter.scratchpad = stubScratchpad;
}
origScratchpad = options.display.inputter.scratchpad;
options.display.inputter.scratchpad = stubScratchpad;
};
exports.shutdown = function(options) {
if (options.display) {
options.display.inputter.scratchpad = origScratchpad;
}
options.display.inputter.scratchpad = origScratchpad;
};
var stubScratchpad = {
@ -72,14 +62,9 @@ stubScratchpad.activate = function(value) {
exports.testActivate = function(options) {
if (!options.display) {
assert.log('No display. Skipping scratchpad tests');
return;
}
var ev = {};
stubScratchpad.activatedCount = 0;
options.display.inputter.onKeyUp(ev);
options.display.inputter.handleKeyUp(ev);
assert.is(1, stubScratchpad.activatedCount, 'scratchpad is activated');
};

Просмотреть файл

@ -25,29 +25,18 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testSpell.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var spell = require('gcli/types/spell');
exports.setup = function() {
};
exports.shutdown = function() {
};
exports.testSpellerSimple = function(options) {
var alternatives = Object.keys(options.window);

Просмотреть файл

@ -26,35 +26,30 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testSplit.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
// var assert = require('test/assert');
'use strict';
// var mockCommands = require('gclitest/mockCommands');
// var assert = require('test/assert');
var Requisition = require('gcli/cli').Requisition;
var canon = require('gcli/canon');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function() {
exports.setup = function(options) {
mockCommands.setup();
};
exports.shutdown = function() {
exports.shutdown = function(options) {
mockCommands.shutdown();
};
exports.testSplitSimple = function() {
exports.testSplitSimple = function(options) {
var args;
var requ = new Requisition();
@ -64,7 +59,7 @@ exports.testSplitSimple = function() {
assert.is('s', requ.commandAssignment.arg.text);
};
exports.testFlatCommand = function() {
exports.testFlatCommand = function(options) {
var args;
var requ = new Requisition();
@ -81,7 +76,7 @@ exports.testFlatCommand = function() {
assert.is('b', args[1].text);
};
exports.testJavascript = function() {
exports.testJavascript = function(options) {
if (!canon.getCommand('{')) {
assert.log('Skipping testJavascript because { is not registered');
return;

Просмотреть файл

@ -26,25 +26,19 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTokenize.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var Requisition = require('gcli/cli').Requisition;
exports.testBlanks = function() {
exports.testBlanks = function(options) {
var args;
var requ = new Requisition();
@ -61,7 +55,7 @@ exports.testBlanks = function() {
assert.is('', args[0].suffix);
};
exports.testTokSimple = function() {
exports.testTokSimple = function(options) {
var args;
var requ = new Requisition();
@ -84,7 +78,7 @@ exports.testTokSimple = function() {
assert.is('Argument', args[1].type);
};
exports.testJavascript = function() {
exports.testJavascript = function(options) {
var args;
var requ = new Requisition();
@ -146,7 +140,7 @@ exports.testJavascript = function() {
assert.is('ScriptArgument', args[0].type);
};
exports.testRegularNesting = function() {
exports.testRegularNesting = function(options) {
var args;
var requ = new Requisition();
@ -179,7 +173,7 @@ exports.testRegularNesting = function() {
assert.is('Argument', args[0].type);
};
exports.testDeepNesting = function() {
exports.testDeepNesting = function(options) {
var args;
var requ = new Requisition();
@ -226,7 +220,7 @@ exports.testDeepNesting = function() {
assert.is('ScriptArgument', args[0].type);
};
exports.testStrangeNesting = function() {
exports.testStrangeNesting = function(options) {
var args;
var requ = new Requisition();
@ -246,7 +240,7 @@ exports.testStrangeNesting = function() {
assert.is('Argument', args[1].type);
};
exports.testComplex = function() {
exports.testComplex = function(options) {
var args;
var requ = new Requisition();
@ -284,7 +278,7 @@ exports.testComplex = function() {
assert.is('Argument', args[2].type);
};
exports.testPathological = function() {
exports.testPathological = function(options) {
var args;
var requ = new Requisition();

Просмотреть файл

@ -26,67 +26,27 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTooltip.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
// var helpers = require('gclitest/helpers');
// var mockCommands = require('gclitest/mockCommands');
exports.setup = function() {
exports.setup = function(options) {
mockCommands.setup();
};
exports.shutdown = function() {
exports.shutdown = function(options) {
mockCommands.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.isJsdom) {
if (tests.important) {
assert.ok(tooltip.field.isImportant, 'Important for ' + typed);
}
else {
assert.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;
});
assert.is(tests.options.join('|'), names.join('|'), 'Options for ' + typed);
}
if (tests.error) {
assert.is(tests.error, tooltip.errorEle.textContent, 'Error for ' + typed);
}
else {
assert.is('', tooltip.errorEle.textContent, 'No error for ' + typed);
}
}
}
exports.testActivate = function(options) {
if (!options.display) {
assert.log('No display. Skipping activate tests');
@ -97,31 +57,106 @@ exports.testActivate = function(options) {
assert.log('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: [ 'true' ]
}, options);
type('wxqy', {
important: false,
options: [ ],
error: 'Can\'t use \'wxqy\'.'
}, options);
type('', { }, options);
return helpers.audit(options, [
{
setup: ' ',
check: {
input: ' ',
hints: '',
markup: 'V',
cursor: 1,
current: '__command',
status: 'ERROR',
message: '',
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'false:default'
}
},
{
setup: 'tsb ',
check: {
input: 'tsb ',
hints: 'false',
markup: 'VVVV',
cursor: 4,
current: 'toggle',
status: 'VALID',
options: [ 'false', 'true' ],
message: '',
predictions: [ 'false', 'true' ],
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'true:importantFieldFlag'
}
},
{
setup: 'tsb t',
check: {
input: 'tsb t',
hints: 'rue',
markup: 'VVVVI',
cursor: 5,
current: 'toggle',
status: 'ERROR',
options: [ 'true' ],
message: '',
predictions: [ 'true' ],
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'true:importantFieldFlag'
}
},
{
setup: 'tsb tt',
check: {
input: 'tsb tt',
hints: ' -> true',
markup: 'VVVVII',
cursor: 6,
current: 'toggle',
status: 'ERROR',
options: [ 'true' ],
message: '',
predictions: [ 'true' ],
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'true:importantFieldFlag'
}
},
{
setup: 'wxqy',
check: {
input: 'wxqy',
hints: '',
markup: 'EEEE',
cursor: 4,
current: '__command',
status: 'ERROR',
options: [ ],
message: 'Can\'t use \'wxqy\'.',
predictions: [ ],
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'true:isError'
}
},
{
setup: '',
check: {
input: '',
hints: '',
markup: '',
cursor: 0,
current: '__command',
status: 'ERROR',
message: '',
unassigned: [ ],
outputState: 'false:default',
tooltipState: 'false:default'
}
}
]);
};
// });

Просмотреть файл

@ -26,47 +26,37 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testTypes.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
'use strict';
// var assert = require('test/assert');
var types = require('gcli/types');
exports.setup = function() {
};
exports.shutdown = function() {
};
function forEachType(options, callback) {
function forEachType(options, typeSpec, callback) {
types.getTypeNames().forEach(function(name) {
options.name = name;
typeSpec.name = name;
typeSpec.requisition = options.display.requisition;
// Provide some basic defaults to help selection/deferred/array work
// Provide some basic defaults to help selection/delegate/array work
if (name === 'selection') {
options.data = [ 'a', 'b' ];
typeSpec.data = [ 'a', 'b' ];
}
else if (name === 'deferred') {
options.defer = function() {
else if (name === 'delegate') {
typeSpec.delegateType = function() {
return types.getType('string');
};
}
else if (name === 'array') {
options.subtype = 'string';
typeSpec.subtype = 'string';
}
var type = types.getType(options);
var type = types.getType(typeSpec);
callback(type);
});
}
@ -77,7 +67,7 @@ exports.testDefault = function(options) {
return;
}
forEachType({}, function(type) {
forEachType(options, {}, function(type) {
var blank = type.getBlank().value;
// boolean and array types are exempt from needing undefined blank values
@ -99,9 +89,10 @@ exports.testDefault = function(options) {
};
exports.testNullDefault = function(options) {
forEachType({ defaultValue: null }, function(type) {
forEachType(options, { defaultValue: null }, function(type) {
assert.is(type.stringify(null), '', 'stringify(null) for ' + type.name);
});
};
// });

Просмотреть файл

@ -26,21 +26,16 @@ var exports = {};
const TEST_URI = "data:text/html;charset=utf-8,<p id='gcli-input'>gcli-testUtil.js</p>";
function test() {
var tests = Object.keys(exports);
// Push setup to the top and shutdown to the bottom
tests.sort(function(t1, t2) {
if (t1 == "setup" || t2 == "shutdown") return -1;
if (t2 == "setup" || t1 == "shutdown") return 1;
return 0;
});
info("Running tests: " + tests.join(", "))
tests = tests.map(function(test) { return exports[test]; });
DeveloperToolbarTest.test(TEST_URI, tests, true);
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.runTests(options, exports);
}).then(finish);
}
// <INJECTED SOURCE:END>
var util = require('gcli/util');
'use strict';
var util = require('util/util');
// var assert = require('test/assert');
exports.testFindCssSelector = function(options) {

Просмотреть файл

@ -5,71 +5,17 @@
const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/commandline/test/";
const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/commandline/test/";
let console = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
return tempScope.console;
})();
let TargetFactory = (function() {
let tempScope = {};
Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
return tempScope.TargetFactory;
})();
let Promise = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js", tempScope);
return tempScope.Promise;
})();
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
Services.scriptloader.loadSubScript(testDir + "/mockCommands.js", this);
Services.scriptloader.loadSubScript(testDir + "/helpers_perwindowpb.js", this);
/**
* Open a new tab at a URL and call a callback on load
* Force GC on shutdown, because it seems that GCLI can outrun the garbage
* collector in some situations, which causes test failures in later tests
* Bug 774619 is an example.
*/
function addTab(aURL, aCallback)
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
if (aURL != null) {
content.location = aURL;
}
let deferred = Promise.defer();
let tab = gBrowser.selectedTab;
let target = TargetFactory.forTab(gBrowser.selectedTab);
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
if (aCallback != null) {
aCallback(browser, tab, browser.contentDocument);
}
deferred.resolve({ browser: browser, tab: tab, target: target });
}
browser.addEventListener("load", onTabLoad, true);
return deferred.promise;
}
registerCleanupFunction(function tearDown() {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
// Force GC, because it seems that GCLI can outrun the garbage collector
// in some situations, which causes test failures in later tests
// Bug 774619 is an example.
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.garbageCollect();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,909 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*
* DO NOT ALTER THIS FILE WITHOUT KEEPING IT IN SYNC WITH THE OTHER COPIES
* OF THIS FILE.
*
* UNAUTHORIZED ALTERATION WILL RESULT IN THE ALTEREE BEING SENT TO SIT ON
* THE NAUGHTY STEP.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* FOR A LONG TIME.
*
*/
/*
* Use as a JSM
* ------------
* helpers_perwindowpb._createDebugCheck() and maybe other functions in this file can be
* useful at runtime, so it is possible to use helpers_perwindowpb.js as a JSM.
* Copy commandline/test/helpers_perwindowpb.js to shared/helpers_perwindowpb.jsm, and then add to
* DeveloperToolbar.jsm the following:
*
* XPCOMUtils.defineLazyModuleGetter(this, "helpers_perwindowpb",
* "resource:///modules/devtools/helpers_perwindowpb.jsm");
*
* At the bottom of DeveloperToolbar.prototype._onload add this:
*
* var options = { display: this.display };
* this._input.onkeypress = function(ev) {
* helpers_perwindowpb.setup(options);
* dump(helpers_perwindowpb._createDebugCheck() + '\n\n');
* };
*
* Now GCLI will emit output on every keypress that both explains the state
* of GCLI and can be run as a test case.
*/
this.EXPORTED_SYMBOLS = [ 'helpers_perwindowpb' ];
var test = { };
/**
* Various functions for testing DeveloperToolbar.
* Parts of this code exist in:
* - browser/devtools/commandline/test/head.js
* - browser/devtools/shared/test/head.js
*/
let DeveloperToolbarTestPW = { };
/**
* Paranoid DeveloperToolbar.show();
*/
DeveloperToolbarTestPW.show = function DTTPW_show(aWindow, aCallback) {
if (aWindow.DeveloperToolbar.visible) {
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
}
else {
aWindow.DeveloperToolbar.show(true, aCallback);
}
};
/**
* Paranoid DeveloperToolbar.hide();
*/
DeveloperToolbarTestPW.hide = function DTTPW_hide(aWindow) {
if (!aWindow.DeveloperToolbar.visible) {
ok(false, "!DeveloperToolbar.visible at start of closeDeveloperToolbar");
}
else {
aWindow.DeveloperToolbar.display.inputter.setInput("");
aWindow.DeveloperToolbar.hide();
}
};
/**
* check() is the new status. Similar API except that it doesn't attempt to
* alter the display/requisition at all, and it makes extra checks.
* Test inputs
* typed: The text to type at the input
* Available checks:
* input: The text displayed in the input field
* cursor: The position of the start of the cursor
* status: One of "VALID", "ERROR", "INCOMPLETE"
* emptyParameters: Array of parameters still to type. e.g. [ "<message>" ]
* directTabText: Simple completion text
* arrowTabText: When the completion is not an extension (without arrow)
* markup: What state should the error markup be in. e.g. "VVVIIIEEE"
* args: Maps of checks to make against the arguments:
* value: i.e. assignment.value (which ignores defaultValue)
* type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
* Care should be taken with this since it's something of an
* implementation detail
* arg: The toString value of the argument
* status: i.e. assignment.getStatus
* message: i.e. assignment.getMessage
* name: For commands - checks assignment.value.name
*/
DeveloperToolbarTestPW.checkInputStatus = function DTTPW_checkInputStatus(aWindow, checks) {
if (!checks.emptyParameters) {
checks.emptyParameters = [];
}
if (!checks.directTabText) {
checks.directTabText = '';
}
if (!checks.arrowTabText) {
checks.arrowTabText = '';
}
var display = aWindow.DeveloperToolbar.display;
if (checks.typed) {
info('Starting tests for ' + checks.typed);
display.inputter.setInput(checks.typed);
}
else {
ok(false, "Missing typed for " + JSON.stringify(checks));
return;
}
if (checks.cursor) {
display.inputter.setCursor(checks.cursor)
}
var cursor = checks.cursor ? checks.cursor.start : checks.typed.length;
var requisition = display.requisition;
var completer = display.completer;
var actual = completer._getCompleterTemplateData();
/*
if (checks.input) {
is(display.inputter.element.value,
checks.input,
'input');
}
if (checks.cursor) {
is(display.inputter.element.selectionStart,
checks.cursor,
'cursor');
}
*/
if (checks.status) {
is(requisition.getStatus().toString(),
checks.status,
'status');
}
if (checks.markup) {
var statusMarkup = requisition.getInputStatusMarkup(cursor);
var actualMarkup = statusMarkup.map(function(s) {
return Array(s.string.length + 1).join(s.status.toString()[0]);
}).join('');
is(checks.markup,
actualMarkup,
'markup');
}
if (checks.emptyParameters) {
var actualParams = actual.emptyParameters;
is(actualParams.length,
checks.emptyParameters.length,
'emptyParameters.length');
if (actualParams.length === checks.emptyParameters.length) {
for (var i = 0; i < actualParams.length; i++) {
is(actualParams[i].replace(/\u00a0/g, ' '),
checks.emptyParameters[i],
'emptyParameters[' + i + ']');
}
}
else {
info('Expected: [ \"' + actualParams.join('", "') + '" ]');
}
}
if (checks.directTabText) {
is(actual.directTabText,
checks.directTabText,
'directTabText');
}
if (checks.arrowTabText) {
is(actual.arrowTabText,
' \u00a0\u21E5 ' + checks.arrowTabText,
'arrowTabText');
}
if (checks.args) {
Object.keys(checks.args).forEach(function(paramName) {
var check = checks.args[paramName];
var assignment;
if (paramName === 'command') {
assignment = requisition.commandAssignment;
}
else {
assignment = requisition.getAssignment(paramName);
}
if (assignment == null) {
ok(false, 'Unknown parameter: ' + paramName);
return;
}
if (check.value) {
is(assignment.value,
check.value,
'checkStatus value for ' + paramName);
}
if (check.name) {
is(assignment.value.name,
check.name,
'checkStatus name for ' + paramName);
}
if (check.type) {
is(assignment.arg.type,
check.type,
'checkStatus type for ' + paramName);
}
if (check.arg) {
is(assignment.arg.toString(),
check.arg,
'checkStatus arg for ' + paramName);
}
if (check.status) {
is(assignment.getStatus().toString(),
check.status,
'checkStatus status for ' + paramName);
}
if (check.message) {
is(assignment.getMessage(),
check.message,
'checkStatus message for ' + paramName);
}
});
}
};
/**
* Execute a command:
*
* DeveloperToolbarTestPW.exec({
* // Test inputs
* typed: "echo hi", // Optional, uses existing if undefined
*
* // Thing to check
* args: { message: "hi" }, // Check that the args were understood properly
* outputMatch: /^hi$/, // RegExp to test against textContent of output
* // (can also be array of RegExps)
* blankOutput: true, // Special checks when there is no output
* });
*/
DeveloperToolbarTestPW.exec = function DTTPW_exec(aWindow, tests) {
tests = tests || {};
if (tests.typed) {
aWindow.DeveloperToolbar.display.inputter.setInput(tests.typed);
}
let typed = aWindow.DeveloperToolbar.display.inputter.getInputState().typed;
let output = aWindow.DeveloperToolbar.display.requisition.exec();
is(typed, output.typed, 'output.command for: ' + typed);
if (tests.completed !== false) {
ok(output.completed, 'output.completed false for: ' + typed);
}
else {
// It is actually an error if we say something is async and it turns
// out not to be? For now we're saying 'no'
// ok(!output.completed, 'output.completed true for: ' + typed);
}
if (tests.args != null) {
is(Object.keys(tests.args).length, Object.keys(output.args).length,
'arg count for ' + typed);
Object.keys(output.args).forEach(function(arg) {
let expectedArg = tests.args[arg];
let actualArg = output.args[arg];
if (typeof expectedArg === 'function') {
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
}
else {
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
ok(false, 'actual is not an array. ' + typed + '/' + arg);
return;
}
is(expectedArg.length, actualArg.length,
'array length: ' + typed + '/' + arg);
for (let i = 0; i < expectedArg.length; i++) {
is(expectedArg[i], actualArg[i],
'member: "' + typed + '/' + arg + '/' + i);
}
}
else {
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
}
}
});
}
let displayed = aWindow.DeveloperToolbar.outputPanel._div.textContent;
if (tests.outputMatch) {
var doTest = function(match, against) {
if (!match.test(against)) {
ok(false, "html output for " + typed + " against " + match.source +
" (textContent sent to info)");
info("Actual textContent");
info(against);
}
}
if (Array.isArray(tests.outputMatch)) {
tests.outputMatch.forEach(function(match) {
doTest(match, displayed);
});
}
else {
doTest(tests.outputMatch, displayed);
}
}
if (tests.blankOutput != null) {
if (!/^$/.test(displayed)) {
ok(false, "html output for " + typed + " (textContent sent to info)");
info("Actual textContent");
info(displayed);
}
}
};
/**
* Quick wrapper around the things you need to do to run DeveloperToolbar
* command tests:
* - Set the pref 'devtools.toolbar.enabled' to true
* - Add a tab pointing at |uri|
* - Open the DeveloperToolbar
* - Register a cleanup function to undo the above
* - Run the tests
*
* @param uri The uri of a page to load. Can be 'about:blank' or 'data:...'
* @param target Either a function or array of functions containing the tests
* to run. If an array of test function is passed then we will clear up after
* the tests have completed. If a single test function is passed then this
* function should arrange for 'finish()' to be called on completion.
*/
DeveloperToolbarTestPW.test = function DTTPW_test(aWindow, uri, target, isGcli, aCallback) {
let menuItem = aWindow.document.getElementById("menu_devToolbar");
let command = aWindow.document.getElementById("Tools:DevToolbar");
let appMenuItem = aWindow.document.getElementById("appmenu_devToolbar");
function cleanup() {
DeveloperToolbarTestPW.hide(aWindow);
// a.k.a Services.prefs.clearUserPref("devtools.toolbar.enabled");
if (menuItem) {
menuItem.hidden = true;
}
if (command) {
command.setAttribute("disabled", "true");
}
if (appMenuItem) {
appMenuItem.hidden = true;
}
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
};
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
if (menuItem) {
menuItem.hidden = false;
}
if (command) {
command.removeAttribute("disabled");
}
if (appMenuItem) {
appMenuItem.hidden = false;
}
let browser = aWindow.gBrowser.selectedBrowser;
browser.addEventListener("load", function onTabLoad() {
if (aWindow.content.location.href != uri) {
browser.loadURI(uri);
return;
}
browser.removeEventListener("load", onTabLoad, true);
DeveloperToolbarTestPW.show(aWindow, function() {
var options = {
window: aWindow.content,
display: aWindow.DeveloperToolbar.display,
isFirefox: true
};
if (helpers_perwindowpb && !isGcli) {
helpers_perwindowpb.setup(options);
}
if (Array.isArray(target)) {
try {
var args = isGcli ? options : aWindow;
var targetCount = 0;
function callTarget() {
if (targetCount < target.length) {
info("Running target test: " + targetCount);
target[targetCount++](args, callTarget);
} else {
info("Clean up and continue test");
cleanup();
aCallback();
}
}
callTarget();
} catch (ex) {
ok(false, "" + ex);
DeveloperToolbarTestPW._finish(aWindow);
throw ex;
}
} else {
try {
target(aWindow, function() {
info("Clean up and continue test");
cleanup();
aCallback();
});
} catch (ex) {
ok(false, "" + ex);
DeveloperToolbarTestPW._finish(aWindow);
throw ex;
}
}
});
}, true);
browser.loadURI(uri);
};
DeveloperToolbarTestPW._outstanding = [];
DeveloperToolbarTestPW._checkFinish = function(aWindow) {
info('_checkFinish. ' + DeveloperToolbarTestPW._outstanding.length + ' outstanding');
if (DeveloperToolbarTestPW._outstanding.length == 0) {
DeveloperToolbarTestPW._finish(aWindow);
}
}
DeveloperToolbarTestPW._finish = function(aWindow) {
info('Finish');
DeveloperToolbarTestPW.closeAllTabs(aWindow);
finish();
}
DeveloperToolbarTestPW.checkCalled = function(aWindow, aFunc, aScope) {
var todo = function() {
var reply = aFunc.apply(aScope, arguments);
DeveloperToolbarTestPW._outstanding = DeveloperToolbarTestPW._outstanding.filter(function(aJob) {
return aJob != todo;
});
DeveloperToolbarTestPW._checkFinish(aWindow);
return reply;
}
DeveloperToolbarTestPW._outstanding.push(todo);
return todo;
};
DeveloperToolbarTestPW.checkNotCalled = function(aMsg, aFunc, aScope) {
return function() {
ok(false, aMsg);
return aFunc.apply(aScope, arguments);
}
};
/**
*
*/
DeveloperToolbarTestPW.closeAllTabs = function(aWindow) {
while (aWindow.gBrowser.tabs.length > 1) {
aWindow.gBrowser.removeCurrentTab();
}
};
///////////////////////////////////////////////////////////////////////////////
this.helpers_perwindowpb = {};
var assert = { ok: ok, is: is, log: info };
helpers_perwindowpb._display = undefined;
helpers_perwindowpb._options = undefined;
helpers_perwindowpb.setup = function(options) {
helpers_perwindowpb._options = options;
helpers_perwindowpb._display = options.display;
};
helpers_perwindowpb.shutdown = function(options) {
helpers_perwindowpb._options = undefined;
helpers_perwindowpb._display = undefined;
};
/**
* Various functions to return the actual state of the command line
*/
helpers_perwindowpb._actual = {
input: function() {
return helpers_perwindowpb._display.inputter.element.value;
},
hints: function() {
var templateData = helpers_perwindowpb._display.completer._getCompleterTemplateData();
var actualHints = templateData.directTabText +
templateData.emptyParameters.join('') +
templateData.arrowTabText;
return actualHints.replace(/\u00a0/g, ' ')
.replace(/\u21E5/, '->')
.replace(/ $/, '');
},
markup: function() {
var cursor = helpers_perwindowpb._display.inputter.element.selectionStart;
var statusMarkup = helpers_perwindowpb._display.requisition.getInputStatusMarkup(cursor);
return statusMarkup.map(function(s) {
return Array(s.string.length + 1).join(s.status.toString()[0]);
}).join('');
},
cursor: function() {
return helpers_perwindowpb._display.inputter.element.selectionStart;
},
current: function() {
return helpers_perwindowpb._display.requisition.getAssignmentAt(helpers_perwindowpb._actual.cursor()).param.name;
},
status: function() {
return helpers_perwindowpb._display.requisition.getStatus().toString();
},
outputState: function() {
var outputData = helpers_perwindowpb._display.focusManager._shouldShowOutput();
return outputData.visible + ':' + outputData.reason;
},
tooltipState: function() {
var tooltipData = helpers_perwindowpb._display.focusManager._shouldShowTooltip();
return tooltipData.visible + ':' + tooltipData.reason;
}
};
helpers_perwindowpb._directToString = [ 'boolean', 'undefined', 'number' ];
helpers_perwindowpb._createDebugCheck = function() {
var requisition = helpers_perwindowpb._display.requisition;
var command = requisition.commandAssignment.value;
var input = helpers_perwindowpb._actual.input();
var padding = Array(input.length + 1).join(' ');
var output = '';
output += 'helpers_perwindowpb.setInput(\'' + input + '\');\n';
output += 'helpers_perwindowpb.check({\n';
output += ' input: \'' + input + '\',\n';
output += ' hints: ' + padding + '\'' + helpers_perwindowpb._actual.hints() + '\',\n';
output += ' markup: \'' + helpers_perwindowpb._actual.markup() + '\',\n';
output += ' cursor: ' + helpers_perwindowpb._actual.cursor() + ',\n';
output += ' current: \'' + helpers_perwindowpb._actual.current() + '\',\n';
output += ' status: \'' + helpers_perwindowpb._actual.status() + '\',\n';
output += ' outputState: \'' + helpers_perwindowpb._actual.outputState() + '\',\n';
if (command) {
output += ' tooltipState: \'' + helpers_perwindowpb._actual.tooltipState() + '\',\n';
output += ' args: {\n';
output += ' command: { name: \'' + command.name + '\' },\n';
requisition.getAssignments().forEach(function(assignment) {
output += ' ' + assignment.param.name + ': { ';
if (typeof assignment.value === 'string') {
output += 'value: \'' + assignment.value + '\', ';
}
else if (helpers_perwindowpb._directToString.indexOf(typeof assignment.value) !== -1) {
output += 'value: ' + assignment.value + ', ';
}
else if (assignment.value === null) {
output += 'value: ' + assignment.value + ', ';
}
else {
output += '/*value:' + assignment.value + ',*/ ';
}
output += 'arg: \'' + assignment.arg + '\', ';
output += 'status: \'' + assignment.getStatus().toString() + '\', ';
output += 'message: \'' + assignment.getMessage() + '\'';
output += ' },\n';
});
output += ' }\n';
}
else {
output += ' tooltipState: \'' + helpers_perwindowpb._actual.tooltipState() + '\'\n';
}
output += '});';
return output;
};
/**
* We're splitting status into setup() which alters the state of the system
* and check() which ensures that things are in the right place afterwards.
*/
helpers_perwindowpb.setInput = function(typed, cursor) {
helpers_perwindowpb._display.inputter.setInput(typed);
if (cursor) {
helpers_perwindowpb._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_perwindowpb._options.isJsdom) {
helpers_perwindowpb._display.inputter.setCursor({
start: typed.length,
end: typed.length
});
}
}
helpers_perwindowpb._display.focusManager.onInputChange();
// Firefox testing is noisy and distant, so logging helps
if (helpers_perwindowpb._options.isFirefox) {
assert.log('setInput("' + typed + '"' + (cursor == null ? '' : ', ' + cursor) + ')');
}
};
/**
* Simulate focusing the input field
*/
helpers_perwindowpb.focusInput = function() {
helpers_perwindowpb._display.inputter.focus();
};
/**
* Simulate pressing TAB in the input field
*/
helpers_perwindowpb.pressTab = function() {
helpers_perwindowpb.pressKey(9 /*KeyEvent.DOM_VK_TAB*/);
};
/**
* Simulate pressing RETURN in the input field
*/
helpers_perwindowpb.pressReturn = function() {
helpers_perwindowpb.pressKey(13 /*KeyEvent.DOM_VK_RETURN*/);
};
/**
* Simulate pressing a key by keyCode in the input field
*/
helpers_perwindowpb.pressKey = function(keyCode) {
var fakeEvent = {
keyCode: keyCode,
preventDefault: function() { },
timeStamp: new Date().getTime()
};
helpers_perwindowpb._display.inputter.onKeyDown(fakeEvent);
helpers_perwindowpb._display.inputter.onKeyUp(fakeEvent);
};
/**
* check() is the new status. Similar API except that it doesn't attempt to
* alter the display/requisition at all, and it makes extra checks.
* Available checks:
* input: The text displayed in the input field
* cursor: The position of the start of the cursor
* status: One of "VALID", "ERROR", "INCOMPLETE"
* hints: The hint text, i.e. a concatenation of the directTabText, the
* emptyParameters and the arrowTabText. The text as inserted into the UI
* will include NBSP and Unicode RARR characters, these should be
* represented using normal space and '->' for the arrow
* markup: What state should the error markup be in. e.g. "VVVIIIEEE"
* args: Maps of checks to make against the arguments:
* value: i.e. assignment.value (which ignores defaultValue)
* type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
* Care should be taken with this since it's something of an
* implementation detail
* arg: The toString value of the argument
* status: i.e. assignment.getStatus
* message: i.e. assignment.getMessage
* name: For commands - checks assignment.value.name
*/
helpers_perwindowpb.check = function(checks) {
if ('input' in checks) {
assert.is(helpers_perwindowpb._actual.input(), checks.input, 'input');
}
if ('cursor' in checks) {
assert.is(helpers_perwindowpb._actual.cursor(), checks.cursor, 'cursor');
}
if ('current' in checks) {
assert.is(helpers_perwindowpb._actual.current(), checks.current, 'current');
}
if ('status' in checks) {
assert.is(helpers_perwindowpb._actual.status(), checks.status, 'status');
}
if ('markup' in checks) {
assert.is(helpers_perwindowpb._actual.markup(), checks.markup, 'markup');
}
if ('hints' in checks) {
assert.is(helpers_perwindowpb._actual.hints(), checks.hints, 'hints');
}
if ('tooltipState' in checks) {
assert.is(helpers_perwindowpb._actual.tooltipState(), checks.tooltipState, 'tooltipState');
}
if ('outputState' in checks) {
assert.is(helpers_perwindowpb._actual.outputState(), checks.outputState, 'outputState');
}
if (checks.args != null) {
var requisition = helpers_perwindowpb._display.requisition;
Object.keys(checks.args).forEach(function(paramName) {
var check = checks.args[paramName];
var assignment;
if (paramName === 'command') {
assignment = requisition.commandAssignment;
}
else {
assignment = requisition.getAssignment(paramName);
}
if (assignment == null) {
assert.ok(false, 'Unknown arg: ' + paramName);
return;
}
if ('value' in check) {
assert.is(assignment.value,
check.value,
'arg.' + paramName + '.value');
}
if ('name' in check) {
assert.is(assignment.value.name,
check.name,
'arg.' + paramName + '.name');
}
if ('type' in check) {
assert.is(assignment.arg.type,
check.type,
'arg.' + paramName + '.type');
}
if ('arg' in check) {
assert.is(assignment.arg.toString(),
check.arg,
'arg.' + paramName + '.arg');
}
if ('status' in check) {
assert.is(assignment.getStatus().toString(),
check.status,
'arg.' + paramName + '.status');
}
if ('message' in check) {
assert.is(assignment.getMessage(),
check.message,
'arg.' + paramName + '.message');
}
});
}
};
/**
* Execute a command:
*
* helpers_perwindowpb.exec({
* // Test inputs
* typed: "echo hi", // Optional, uses existing if undefined
*
* // Thing to check
* args: { message: "hi" }, // Check that the args were understood properly
* outputMatch: /^hi$/, // Regex to test against textContent of output
* blankOutput: true, // Special checks when there is no output
* });
*/
helpers_perwindowpb.exec = function(tests) {
var requisition = helpers_perwindowpb._display.requisition;
var inputter = helpers_perwindowpb._display.inputter;
tests = tests || {};
if (tests.typed) {
inputter.setInput(tests.typed);
}
var typed = inputter.getInputState().typed;
var output = requisition.exec({ hidden: true });
assert.is(typed, output.typed, 'output.command for: ' + typed);
if (tests.completed !== false) {
assert.ok(output.completed, 'output.completed false for: ' + typed);
}
else {
// It is actually an error if we say something is async and it turns
// out not to be? For now we're saying 'no'
// assert.ok(!output.completed, 'output.completed true for: ' + typed);
}
if (tests.args != null) {
assert.is(Object.keys(tests.args).length, Object.keys(output.args).length,
'arg count for ' + typed);
Object.keys(output.args).forEach(function(arg) {
var expectedArg = tests.args[arg];
var actualArg = output.args[arg];
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
assert.ok(false, 'actual is not an array. ' + typed + '/' + arg);
return;
}
assert.is(expectedArg.length, actualArg.length,
'array length: ' + typed + '/' + arg);
for (var i = 0; i < expectedArg.length; i++) {
assert.is(expectedArg[i], actualArg[i],
'member: "' + typed + '/' + arg + '/' + i);
}
}
else {
assert.is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
}
});
}
if (!helpers_perwindowpb._options.window.document.createElement) {
assert.log('skipping output tests (missing doc.createElement) for ' + typed);
return;
}
var div = helpers_perwindowpb._options.window.document.createElement('div');
output.toDom(div);
var displayed = div.textContent.trim();
if (tests.outputMatch) {
var doTest = function(match, against) {
if (!match.test(against)) {
assert.ok(false, "html output for " + typed + " against " + match.source);
console.log("Actual textContent");
console.log(against);
}
}
if (Array.isArray(tests.outputMatch)) {
tests.outputMatch.forEach(function(match) {
doTest(match, displayed);
});
}
else {
doTest(tests.outputMatch, displayed);
}
}
if (tests.blankOutput != null) {
if (!/^$/.test(displayed)) {
assert.ok(false, "html for " + typed + " (textContent sent to info)");
console.log("Actual textContent");
console.log(displayed);
}
}
};

Просмотреть файл

@ -21,43 +21,29 @@
// THIS FILE IS GENERATED FROM SOURCE IN THE GCLI PROJECT
// DO NOT EDIT IT DIRECTLY
let [ define, require ] = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/devtools/Require.jsm", tempScope);
return [ tempScope.define, tempScope.require ];
})();
registerCleanupFunction(function mockTearDown() {
define = undefined;
require = undefined;
});
let gcli = (function() {
let tempScope = {};
Components.utils.import("resource:///modules/devtools/gcli.jsm", tempScope);
return tempScope.gcli;
})();
registerCleanupFunction(function mockTearDown() {
gcli = undefined;
});
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
let { require: require, define: define } = Cu.import("resource://gre/modules/devtools/Require.jsm", {});
Cu.import("resource:///modules/devtools/gcli.jsm", {});
// <INJECTED SOURCE:END>
var mockCommands = {};
var util = require('util/util');
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');
var SelectionType = require('gcli/types/selection').SelectionType;
var DelegateType = require('gcli/types/basic').DelegateType;
/**
* Registration and de-registration.
*/
mockCommands.setup = function() {
// setup/shutdown need to register/unregister types, however that means we
// need to re-initialize exports.option1 and exports.option2 with the
// actual types
mockCommands.setup = function(opts) {
// setup/shutdown needs to register/unregister types, however that means we
// need to re-initialize mockCommands.option1 and mockCommands.option2 with
// the actual types
mockCommands.option1.type = types.getType('string');
mockCommands.option2.type = types.getType('number');
@ -91,7 +77,7 @@ mockCommands.setup = function() {
canon.addCommand(mockCommands.tslong);
};
mockCommands.shutdown = function() {
mockCommands.shutdown = function(opts) {
canon.removeCommand(mockCommands.tsv);
canon.removeCommand(mockCommands.tsr);
canon.removeCommand(mockCommands.tso);
@ -127,6 +113,7 @@ mockCommands.option1 = { type: types.getType('string') };
mockCommands.option2 = { type: types.getType('number') };
var lastOption = undefined;
var debug = false;
mockCommands.optionType = new SelectionType({
name: 'optionType',
@ -136,21 +123,32 @@ mockCommands.optionType = new SelectionType({
],
noMatch: function() {
lastOption = undefined;
if (debug) {
console.log('optionType.noMatch: lastOption = undefined');
}
},
stringify: function(option) {
lastOption = option;
if (debug) {
console.log('optionType.stringify: lastOption = ', lastOption);
}
return SelectionType.prototype.stringify.call(this, option);
},
parse: function(arg) {
var conversion = SelectionType.prototype.parse.call(this, arg);
lastOption = conversion.value;
return conversion;
var promise = SelectionType.prototype.parse.call(this, arg);
promise.then(function(conversion) {
lastOption = conversion.value;
if (debug) {
console.log('optionType.parse: lastOption = ', lastOption);
}
});
return promise;
}
});
mockCommands.optionValue = new DeferredType({
mockCommands.optionValue = new DelegateType({
name: 'optionValue',
defer: function() {
delegateType: function() {
if (lastOption && lastOption.type) {
return lastOption.type;
}
@ -170,7 +168,10 @@ function createExec(name) {
context: context
};
mockCommands.onCommandExec(data);
return data;
var argsOut = Object.keys(args).map(function(key) {
return key + '=' + args[key];
}).join(', ');
return 'Exec: ' + name + ' ' + argsOut;
};
}
@ -259,13 +260,13 @@ mockCommands.tsnExt = {
mockCommands.tsnExte = {
name: 'tsn exte',
params: [ { name: 'text', type: 'string' } ],
exec: createExec('')
exec: createExec('tsnExte')
};
mockCommands.tsnExten = {
name: 'tsn exten',
params: [ { name: 'text', type: 'string' } ],
exec: createExec('tsnExte')
exec: createExec('tsnExten')
};
mockCommands.tsnExtend = {
@ -275,15 +276,15 @@ mockCommands.tsnExtend = {
};
mockCommands.tsnDeep = {
name: 'tsn deep',
name: 'tsn deep'
};
mockCommands.tsnDeepDown = {
name: 'tsn deep down',
name: 'tsn deep down'
};
mockCommands.tsnDeepDownNested = {
name: 'tsn deep down nested',
name: 'tsn deep down nested'
};
mockCommands.tsnDeepDownNestedCmd = {
@ -327,7 +328,7 @@ mockCommands.tselarr = {
name: 'tselarr',
params: [
{ name: 'num', type: { name: 'selection', data: [ '1', '2', '3' ] } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } },
{ name: 'arr', type: { name: 'array', subtype: 'string' } }
],
exec: createExec('tselarr')
};
@ -338,7 +339,7 @@ mockCommands.tsm = {
params: [
{ name: 'abc', type: { name: 'selection', data: [ 'a', 'b', 'c' ] } },
{ name: 'txt', type: 'string' },
{ name: 'num', type: { name: 'number', max: 42, min: 0 } },
{ name: 'num', type: { name: 'number', max: 42, min: 0 } }
],
exec: createExec('tsm')
};
@ -458,7 +459,7 @@ mockCommands.tslong = {
]
},
description: 'sel Desc',
defaultValue: ' ',
defaultValue: ' '
},
{
name: 'bool',

Просмотреть файл

@ -0,0 +1,361 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
this.EXPORTED_SYMBOLS = [ ];
Cu.import("resource:///modules/devtools/gcli.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
/**
* 'break' command
*/
gcli.addCommand({
name: "break",
description: gcli.lookup("breakDesc"),
manual: gcli.lookup("breakManual")
});
/**
* 'break list' command
*/
gcli.addCommand({
name: "break list",
description: gcli.lookup("breaklistDesc"),
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
if (Object.keys(breakpoints).length === 0) {
return gcli.lookup("breaklistNone");
}
let reply = gcli.lookup("breaklistIntro");
reply += "<ol>";
for each (let breakpoint in breakpoints) {
let text = gcli.lookupFormat("breaklistLineEntry",
[breakpoint.location.url,
breakpoint.location.line]);
reply += "<li>" + text + "</li>";
};
reply += "</ol>";
return reply;
}
});
/**
* 'break add' command
*/
gcli.addCommand({
name: "break add",
description: gcli.lookup("breakaddDesc"),
manual: gcli.lookup("breakaddManual")
});
/**
* 'break add line' command
*/
gcli.addCommand({
name: "break add line",
description: gcli.lookup("breakaddlineDesc"),
params: [
{
name: "file",
type: {
name: "selection",
data: function(args, context) {
let files = [];
let dbg = getPanel(context, "jsdebugger");
if (dbg) {
let sourcesView = dbg.panelWin.DebuggerView.Sources;
for (let item in sourcesView) {
files.push(item.value);
}
}
return files;
}
},
description: gcli.lookup("breakaddlineFileDesc")
},
{
name: "line",
type: { name: "number", min: 1, step: 10 },
description: gcli.lookup("breakaddlineLineDesc")
}
],
returnType: "html",
exec: function(args, context) {
args.type = "line";
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
var deferred = context.defer();
let position = { url: args.file, line: args.line };
dbg.addBreakpoint(position, function(aBreakpoint, aError) {
if (aError) {
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
return;
}
deferred.resolve(gcli.lookup("breakaddAdded"));
});
return deferred.promise;
}
});
/**
* 'break del' command
*/
gcli.addCommand({
name: "break del",
description: gcli.lookup("breakdelDesc"),
params: [
{
name: "breakid",
type: {
name: "number",
min: 0,
max: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
return dbg == null ?
null :
Object.keys(dbg.getAllBreakpoints()).length - 1;
},
},
description: gcli.lookup("breakdelBreakidDesc")
}
],
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let breakpoints = dbg.getAllBreakpoints();
let id = Object.keys(breakpoints)[args.breakid];
if (!id || !(id in breakpoints)) {
return gcli.lookup("breakNotFound");
}
let deferred = context.defer();
try {
dbg.removeBreakpoint(breakpoints[id], function() {
deferred.resolve(gcli.lookup("breakdelRemoved"));
});
} catch (ex) {
// If the debugger has been closed already, don't scare the user.
deferred.resolve(gcli.lookup("breakdelRemoved"));
}
return deferred.promise;
}
});
/**
* 'dbg' command
*/
gcli.addCommand({
name: "dbg",
description: gcli.lookup("dbgDesc"),
manual: gcli.lookup("dbgManual")
});
/**
* 'dbg open' command
*/
gcli.addCommand({
name: "dbg open",
description: gcli.lookup("dbgOpen"),
params: [],
exec: function(args, context) {
return gDevTools.showToolbox(context.environment.target, "jsdebugger").then(function() null);
}
});
/**
* 'dbg close' command
*/
gcli.addCommand({
name: "dbg close",
description: gcli.lookup("dbgClose"),
params: [],
exec: function(args, context) {
return gDevTools.closeToolbox(context.environment.target).then(function() null);
}
});
/**
* 'dbg interrupt' command
*/
gcli.addCommand({
name: "dbg interrupt",
description: gcli.lookup("dbgInterrupt"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (!thread.paused) {
thread.interrupt();
}
}
});
/**
* 'dbg continue' command
*/
gcli.addCommand({
name: "dbg continue",
description: gcli.lookup("dbgContinue"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.resume();
}
}
});
/**
* 'dbg step' command
*/
gcli.addCommand({
name: "dbg step",
description: gcli.lookup("dbgStepDesc"),
manual: gcli.lookup("dbgStepManual")
});
/**
* 'dbg step over' command
*/
gcli.addCommand({
name: "dbg step over",
description: gcli.lookup("dbgStepOverDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOver();
}
}
});
/**
* 'dbg step in' command
*/
gcli.addCommand({
name: 'dbg step in',
description: gcli.lookup("dbgStepInDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepIn();
}
}
});
/**
* 'dbg step over' command
*/
gcli.addCommand({
name: 'dbg step out',
description: gcli.lookup("dbgStepOutDesc"),
params: [],
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
}
let controller = dbg._controller;
let thread = controller.activeThread;
if (thread.paused) {
thread.stepOut();
}
}
});
/**
* 'dbg list' command
*/
gcli.addCommand({
name: "dbg list",
description: gcli.lookup("dbgListSourcesDesc"),
params: [],
returnType: "html",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
let doc = context.environment.chromeDocument;
if (!dbg) {
return gcli.lookup("debuggerClosed");
}
let sources = dbg._view.Sources.values;
let div = createXHTMLElement(doc, "div");
let ol = createXHTMLElement(doc, "ol");
sources.forEach(function(src) {
let li = createXHTMLElement(doc, "li");
li.textContent = src;
ol.appendChild(li);
});
div.appendChild(ol);
return div;
}
});
/**
* A helper to create xhtml namespaced elements
*/
function createXHTMLElement(document, tagname) {
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
}
/**
* A helper to go from a command context to a debugger panel
*/
function getPanel(context, id) {
if (context == null) {
return undefined;
}
let toolbox = gDevTools.getToolbox(context.environment.target);
return toolbox == null ? undefined : toolbox.getPanel(id);
}

Просмотреть файл

@ -11,6 +11,8 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_TESTS = \
$(browser_dbg_cmd_break.js disabled until bug 722727 is fixed) \
browser_dbg_cmd.js \
browser_dbg_aaa_run_first_leaktest.js \
browser_dbg_clean-exit.js \
browser_dbg_createChrome.js \
@ -95,9 +97,12 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_progress-listener-bug.js \
browser_dbg_chrome-debugging.js \
head.js \
helpers.js \
$(NULL)
MOCHITEST_BROWSER_PAGES = \
browser_dbg_cmd_break.html \
browser_dbg_cmd.html \
testactors.js \
browser_dbg_tab1.html \
browser_dbg_tab2.html \

Просмотреть файл

@ -0,0 +1,106 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
const TEST_URI = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_cmd.html";
helpers.addTabWithToolbar(TEST_URI, function(options) {
let deferred = Promise.defer();
let openDone = helpers.audit(options, [{
setup: "dbg open",
exec: { output: "", completed: false }
}]);
openDone.then(function() {
gDevTools.showToolbox(options.target, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
function cmd(typed, callback) {
dbg._controller.activeThread.addOneTimeListener("paused", callback);
helpers.audit(options, [{
setup: typed,
exec: { output: "" }
}]);
}
let testCommands = function(dbg, cmd) {
// Wait for the initial resume...
dbg._controller.activeThread.addOneTimeListener("resumed", function() {
info("Starting tests");
let contentDoc = content.window.document;
let output = contentDoc.querySelector("input[type=text]");
let btnDoit = contentDoc.querySelector("input[type=button]");
helpers.audit(options, [{
setup: "dbg list",
exec: { output: /browser_dbg_cmd.html/ }
}]);
cmd("dbg interrupt", function() {
ok(true, "debugger is paused");
dbg._controller.activeThread.addOneTimeListener("resumed", function() {
ok(true, "debugger continued");
dbg._controller.activeThread.addOneTimeListener("paused", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
cmd("dbg step in", function() {
is(output.value, "step in", "debugger stepped in");
cmd("dbg step over", function() {
is(output.value, "step over", "debugger stepped over");
cmd("dbg step out", function() {
is(output.value, "step out", "debugger stepped out");
cmd("dbg continue", function() {
cmd("dbg continue", function() {
is(output.value, "dbg continue", "debugger continued");
helpers.audit(options, [{
setup: "dbg close",
completed: false,
exec: { output: "" }
}]);
let toolbox = gDevTools.getToolbox(options.target);
if (!toolbox) {
ok(true, "Debugger was closed.");
deferred.resolve();
} else {
toolbox.on("destroyed", function () {
ok(true, "Debugger was closed.");
deferred.resolve();
});
}
});
});
});
});
});
});
});
});
EventUtils.sendMouseEvent({type:"click"}, btnDoit);
});
helpers.audit(options, [{
setup: "dbg continue",
exec: { output: "" }
}]);
});
});
};
if (dbg._controller.activeThread) {
testCommands(dbg, cmd);
} else {
dbg.once("connected", testCommands.bind(null, dbg, cmd));
}
});
});
return deferred.promise;
}).then(finish);
}

Просмотреть файл

@ -0,0 +1,152 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the break command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_cmd_break.html";
function test() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
// To help us run later commands, and clear up after ourselves
let client, line0;
return helpers.audit(options, [
{
setup: 'break',
check: {
input: 'break',
hints: '',
markup: 'IIIII',
status: 'ERROR',
},
},
{
setup: 'break add',
check: {
input: 'break add',
hints: '',
markup: 'IIIIIVIII',
status: 'ERROR'
},
},
{
setup: 'break add line',
check: {
input: 'break add line',
hints: ' <file> <line>',
markup: 'VVVVVVVVVVVVVV',
status: 'ERROR'
},
},
{
name: 'open toolbox',
setup: function() {
var deferred = Promise.defer();
var openDone = gDevTools.showToolbox(options.target, "jsdebugger");
openDone.then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
dbg.once("connected", function() {
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
dbg._view.Variables.lazyEmpty = false;
client = dbg.panelWin.gClient;
client.activeThread.addOneTimeListener("framesadded", function() {
line0 = '' + options.window.wrappedJSObject.line0;
deferred.resolve();
});
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
});
});
return deferred.promise;
},
post: function() {
ok(client, "Debugger client exists");
is(line0, 10, "line0 is 10");
},
},
{
name: 'break add line .../browser_dbg_cmd_break.html 10',
setup: function() {
// We have to setup in a function to allow line0 to be initialized
let line = 'break add line ' + TEST_URI + ' ' + line0;
return helpers.setInput(options, line);
},
check: {
hints: '',
status: 'VALID',
message: '',
args: {
file: { value: TEST_URI, message: '' },
line: { value: 10 }, // would like to use line0, but see above
// if this proves to be too fragile, disable
}
},
exec: {
output: '',
completed: false
},
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ''
},
},
{
name: 'cleanup',
setup: function() {
var deferred = Promise.defer();
client.activeThread.resume(function() {
deferred.resolve();
});
return deferred.promise;
},
},
{
setup: 'break del 9',
check: {
input: 'break del 9',
hints: '',
markup: 'VVVVVVVVVVE',
status: 'ERROR',
args: {
breakid: {
status: 'ERROR',
message: '9 is greater than maximum allowed: 0.'
},
}
},
},
{
setup: 'break del 0',
check: {
input: 'break del 0',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID',
args: {
breakid: { value: 0 },
}
},
exec: {
output: '',
completed: false
},
},
]);
}).then(finish);
}

Просмотреть файл

@ -21,6 +21,10 @@ let DebuggerClient = tempScope.DebuggerClient;
let gDevTools = tempScope.gDevTools;
let TargetFactory = tempScope.TargetFactory;
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html";
const TAB2_URL = EXAMPLE_URL + "browser_dbg_tab2.html";

Просмотреть файл

@ -0,0 +1,992 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Use as a JSM
// ------------
// helpers._createDebugCheck() can be useful at runtime. To use as a JSM, copy
// commandline/test/helpers.js to shared/helpers.jsm, and then import to
// DeveloperToolbar.jsm with:
// XPCOMUtils.defineLazyModuleGetter(this, "helpers",
// "resource:///modules/devtools/helpers.jsm");
// At the bottom of DeveloperToolbar.prototype._onload add this:
// var options = { display: this.display };
// this._input.onkeypress = function(ev) {
// helpers.setup(options);
// dump(helpers._createDebugCheck() + '\n\n');
// };
// Now GCLI will emit output on every keypress that both explains the state
// of GCLI and can be run as a test case.
this.EXPORTED_SYMBOLS = [ 'helpers' ];
var helpers = {};
this.helpers = helpers;
let require = (Cu.import("resource://gre/modules/devtools/Require.jsm", {})).require;
Components.utils.import("resource:///modules/devtools/gcli.jsm", {});
let console = (Cu.import("resource://gre/modules/devtools/Console.jsm", {})).console;
let TargetFactory = (Cu.import("resource:///modules/devtools/Target.jsm", {})).TargetFactory;
let Promise = (Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {})).Promise;
let assert = { ok: ok, is: is, log: info };
var util = require('util/util');
/**
* Warning: For use with Firefox Mochitests only.
*
* Open a new tab at a URL and call a callback on load, and then tidy up when
* the callback finishes.
* The function will be passed a set of test options, and will usually return a
* promise to indicate that the tab can be cleared up. (To be formal, we call
* Promise.resolve() on the return value of the callback function)
*
* The options used by addTab include:
* - chromeWindow: XUL window parent of created tab. a.k.a 'window' in mochitest
* - tab: The new XUL tab element, as returned by gBrowser.addTab()
* - target: The debug target as defined by the devtools framework
* - browser: The XUL browser element for the given tab
* - window: Content window for the created tab. a.k.a 'content' in mochitest
* - isFirefox: Always true. Allows test sharing with GCLI
*
* Normally addTab will create an options object containing the values as
* described above. However these options can be customized by the third
* 'options' parameter. This has the ability to customize the value of
* chromeWindow or isFirefox, and to add new properties.
*
* @param url The URL for the new tab
* @param callback The function to call on page load
* @param options An optional set of options to customize the way the tests run
*/
helpers.addTab = function(url, callback, options) {
var deferred = Promise.defer();
waitForExplicitFinish();
options = options || {};
options.chromeWindow = options.chromeWindow || window;
options.isFirefox = true;
var tabbrowser = options.chromeWindow.gBrowser;
options.tab = tabbrowser.addTab();
tabbrowser.selectedTab = options.tab;
options.browser = tabbrowser.getBrowserForTab(options.tab);
options.target = TargetFactory.forTab(options.tab);
var onPageLoad = function() {
options.browser.removeEventListener("load", onPageLoad, true);
options.document = options.browser.contentDocument;
options.window = options.document.defaultView;
var cleanUp = function() {
tabbrowser.removeTab(options.tab);
delete options.window;
delete options.document;
delete options.target;
delete options.browser;
delete options.tab;
delete options.chromeWindow;
delete options.isFirefox;
deferred.resolve();
};
var reply = callback(options);
Promise.resolve(reply).then(cleanUp, function(error) {
ok(false, error);
cleanUp();
});
};
options.browser.contentWindow.location = url;
options.browser.addEventListener("load", onPageLoad, true);
return deferred.promise;
};
/**
* Warning: For use with Firefox Mochitests only.
*
* As addTab, but that also opens the developer toolbar. In addition a new
* 'display' property is added to the options object with the display from GCLI
* in the developer toolbar
*/
helpers.addTabWithToolbar = function(url, callback, options) {
return helpers.addTab(url, function(innerOptions) {
var win = innerOptions.chromeWindow;
var deferred = Promise.defer();
win.DeveloperToolbar.show(true, function() {
innerOptions.display = win.DeveloperToolbar.display;
var cleanUp = function() {
win.DeveloperToolbar.hide();
delete innerOptions.display;
deferred.resolve();
};
var reply = callback(innerOptions);
Promise.resolve(reply).then(cleanUp, function(error) {
ok(false, error);
cleanUp();
});
});
return deferred.promise;
}, options);
};
/**
* Warning: For use with Firefox Mochitests only.
*
* Run a set of test functions stored in the values of the 'exports' object
* functions stored under setup/shutdown will be run at the start/end of the
* sequence of tests.
* A test will be considered finished when its return value is resolved.
* @param options An object to be passed to the test functions
* @param tests An object containing named test functions
* @return a promise which will be resolved when all tests have been run and
* their return values resolved
*/
helpers.runTests = function(options, tests) {
var testNames = Object.keys(tests).filter(function(test) {
return test != "setup" && test != "shutdown";
});
var recover = function(error) {
console.error(error);
};
info("SETUP");
var setupDone = (tests.setup != null) ?
Promise.resolve(tests.setup(options)) :
Promise.resolve();
var testDone = setupDone.then(function() {
return util.promiseEach(testNames, function(testName) {
info(testName);
var action = tests[testName];
if (typeof action === "function") {
var reply = action.call(tests, options);
return Promise.resolve(reply);
}
else if (Array.isArray(action)) {
return helpers.audit(options, action);
}
return Promise.reject("test action '" + testName +
"' is not a function or helpers.audit() object");
});
}, recover);
return testDone.then(function() {
info("SHUTDOWN");
return (tests.shutdown != null) ?
Promise.resolve(tests.shutdown(options)) :
Promise.resolve();
}, recover);
};
///////////////////////////////////////////////////////////////////////////////
function checkOptions(options) {
if (options == null) {
console.trace();
throw new Error('Missing options object');
}
if (options.display == null) {
console.trace();
throw new Error('options object does not contain a display property');
}
if (options.display.requisition == null) {
console.trace();
throw new Error('display object does not contain a requisition');
}
}
/**
* Various functions to return the actual state of the command line
*/
helpers._actual = {
input: function(options) {
return options.display.inputter.element.value;
},
hints: function(options) {
var templateData = options.display.completer._getCompleterTemplateData();
var join = function(directTabText, emptyParameters, arrowTabText) {
return (directTabText + emptyParameters.join('') + arrowTabText)
.replace(/\u00a0/g, ' ')
.replace(/\u21E5/, '->')
.replace(/ $/, '');
};
var promisedJoin = util.promised(join);
return promisedJoin(templateData.directTabText,
templateData.emptyParameters,
templateData.arrowTabText);
},
markup: function(options) {
var cursor = options.display.inputter.element.selectionStart;
var statusMarkup = options.display.requisition.getInputStatusMarkup(cursor);
return statusMarkup.map(function(s) {
return Array(s.string.length + 1).join(s.status.toString()[0]);
}).join('');
},
cursor: function(options) {
return options.display.inputter.element.selectionStart;
},
current: function(options) {
return options.display.requisition.getAssignmentAt(helpers._actual.cursor(options)).param.name;
},
status: function(options) {
return options.display.requisition.getStatus().toString();
},
predictions: function(options) {
var cursor = options.display.inputter.element.selectionStart;
var assignment = options.display.requisition.getAssignmentAt(cursor);
return assignment.getPredictions().then(function(predictions) {
return predictions.map(function(prediction) {
return prediction.name;
});
});
},
unassigned: function(options) {
return options.display.requisition._unassigned.map(function(assignment) {
return assignment.arg.toString();
}.bind(this));
},
outputState: function(options) {
var outputData = options.display.focusManager._shouldShowOutput();
return outputData.visible + ':' + outputData.reason;
},
tooltipState: function(options) {
var tooltipData = options.display.focusManager._shouldShowTooltip();
return tooltipData.visible + ':' + tooltipData.reason;
},
options: function(options) {
if (options.display.tooltip.field.menu == null) {
return [];
}
return options.display.tooltip.field.menu.items.map(function(item) {
return item.name.textContent ? item.name.textContent : item.name;
});
},
message: function(options) {
return options.display.tooltip.errorEle.textContent;
}
};
function shouldOutputUnquoted(value) {
var type = typeof value;
return value == null || type === 'boolean' || type === 'number';
}
function outputArray(array) {
return (array.length === 0) ?
'[ ]' :
'[ \'' + array.join('\', \'') + '\' ]';
}
helpers._createDebugCheck = function(options) {
checkOptions(options);
var requisition = options.display.requisition;
var command = requisition.commandAssignment.value;
var cursor = helpers._actual.cursor(options);
var input = helpers._actual.input(options);
var padding = Array(input.length + 1).join(' ');
var hintsPromise = helpers._actual.hints(options);
var predictionsPromise = helpers._actual.predictions(options);
return util.all(hintsPromise, predictionsPromise).then(function(values) {
var hints = values[0];
var predictions = values[1];
var output = '';
output += 'helpers.audit(options, [\n';
output += ' {\n';
if (cursor === input.length) {
output += ' setup: \'' + input + '\',\n';
}
else {
output += ' name: \'' + input + ' (cursor=' + cursor + ')\',\n';
output += ' setup: function() {\n';
output += ' return helpers.setInput(options, \'' + input + '\', ' + cursor + ');\n';
output += ' },\n';
}
output += ' check: {\n';
output += ' input: \'' + input + '\',\n';
output += ' hints: ' + padding + '\'' + hints + '\',\n';
output += ' markup: \'' + helpers._actual.markup(options) + '\',\n';
output += ' cursor: ' + cursor + ',\n';
output += ' current: \'' + helpers._actual.current(options) + '\',\n';
output += ' status: \'' + helpers._actual.status(options) + '\',\n';
output += ' options: ' + outputArray(helpers._actual.options(options)) + ',\n';
output += ' error: \'' + helpers._actual.message(options) + '\',\n';
output += ' predictions: ' + outputArray(predictions) + ',\n';
output += ' unassigned: ' + outputArray(requisition._unassigned) + ',\n';
output += ' outputState: \'' + helpers._actual.outputState(options) + '\',\n';
output += ' tooltipState: \'' + helpers._actual.tooltipState(options) + '\'' +
(command ? ',' : '') +'\n';
if (command) {
output += ' args: {\n';
output += ' command: { name: \'' + command.name + '\' },\n';
requisition.getAssignments().forEach(function(assignment) {
output += ' ' + assignment.param.name + ': { ';
if (typeof assignment.value === 'string') {
output += 'value: \'' + assignment.value + '\', ';
}
else if (shouldOutputUnquoted(assignment.value)) {
output += 'value: ' + assignment.value + ', ';
}
else {
output += '/*value:' + assignment.value + ',*/ ';
}
output += 'arg: \'' + assignment.arg + '\', ';
output += 'status: \'' + assignment.getStatus().toString() + '\', ';
output += 'message: \'' + assignment.getMessage() + '\'';
output += ' },\n';
});
output += ' }\n';
}
output += ' },\n';
output += ' exec: {\n';
output += ' output: \'\',\n';
output += ' completed: true,\n';
output += ' }\n';
output += ' }\n';
output += ']);';
return output;
}.bind(this), console.error);
};
/**
* Simulate focusing the input field
*/
helpers.focusInput = function(options) {
checkOptions(options);
options.display.inputter.focus();
};
/**
* Simulate pressing TAB in the input field
*/
helpers.pressTab = function(options) {
checkOptions(options);
return helpers.pressKey(options, 9 /*KeyEvent.DOM_VK_TAB*/);
};
/**
* Simulate pressing RETURN in the input field
*/
helpers.pressReturn = function(options) {
checkOptions(options);
return helpers.pressKey(options, 13 /*KeyEvent.DOM_VK_RETURN*/);
};
/**
* Simulate pressing a key by keyCode in the input field
*/
helpers.pressKey = function(options, keyCode) {
checkOptions(options);
var fakeEvent = {
keyCode: keyCode,
preventDefault: function() { },
timeStamp: new Date().getTime()
};
options.display.inputter.onKeyDown(fakeEvent);
return options.display.inputter.handleKeyUp(fakeEvent);
};
/**
* A list of special key presses and how to to them, for the benefit of
* helpers.setInput
*/
var ACTIONS = {
'<TAB>': function(options) {
return helpers.pressTab(options);
},
'<RETURN>': function(options) {
return helpers.pressReturn(options);
},
'<UP>': function(options) {
return helpers.pressKey(options, 38 /*KeyEvent.DOM_VK_UP*/);
},
'<DOWN>': function(options) {
return helpers.pressKey(options, 40 /*KeyEvent.DOM_VK_DOWN*/);
}
};
/**
* Used in helpers.setInput to cut an input string like "blah<TAB>foo<UP>" into
* an array like [ "blah", "<TAB>", "foo", "<UP>" ].
* When using this RegExp, you also need to filter out the blank strings.
*/
var CHUNKER = /([^<]*)(<[A-Z]+>)/;
/**
* Alter the input to <code>typed</code> optionally leaving the cursor at
* <code>cursor</code>.
* @return A promise of the number of key-presses to respond
*/
helpers.setInput = function(options, typed, cursor) {
checkOptions(options);
var promise = undefined;
var inputter = options.display.inputter;
// We try to measure average keypress time, but setInput can simulate
// several, so we try to keep track of how many
var chunkLen = 1;
// The easy case is a simple string without things like <TAB>
if (typed.indexOf('<') === -1) {
promise = inputter.setInput(typed);
}
else {
// Cut the input up into input strings separated by '<KEY>' tokens. The
// CHUNKS RegExp leaves blanks so we filter them out.
var chunks = typed.split(CHUNKER).filter(function(s) {
return s != '';
});
chunkLen = chunks.length + 1;
// We're working on this in chunks so first clear the input
promise = inputter.setInput('').then(function() {
return util.promiseEach(chunks, function(chunk) {
if (chunk.charAt(0) === '<') {
var action = ACTIONS[chunk];
if (typeof action !== 'function') {
console.error('Known actions: ' + Object.keys(ACTIONS).join());
throw new Error('Key action not found "' + chunk + '"');
}
return action(options);
}
else {
return inputter.setInput(inputter.element.value + chunk);
}
});
});
}
return promise.then(function() {
if (cursor != null) {
options.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 (options.isJsdom) {
options.display.inputter.setCursor({
start: typed.length,
end: typed.length
});
}
}
options.display.focusManager.onInputChange();
// Firefox testing is noisy and distant, so logging helps
if (options.isFirefox) {
var cursorStr = (cursor == null ? '' : ', ' + cursor);
log('setInput("' + typed + '"' + cursorStr + ')');
}
return chunkLen;
});
};
/**
* Helper for helpers.audit() to ensure that all the 'check' properties match.
* See helpers.audit for more information.
* @param name The name to use in error messages
* @param checks See helpers.audit for a list of available checks
* @return A promise which resolves to undefined when the checks are complete
*/
helpers._check = function(options, name, checks) {
if (checks == null) {
return Promise.resolve();
}
var outstanding = [];
var suffix = name ? ' (for \'' + name + '\')' : '';
if ('input' in checks) {
assert.is(helpers._actual.input(options), checks.input, 'input' + suffix);
}
if ('cursor' in checks) {
assert.is(helpers._actual.cursor(options), checks.cursor, 'cursor' + suffix);
}
if ('current' in checks) {
assert.is(helpers._actual.current(options), checks.current, 'current' + suffix);
}
if ('status' in checks) {
assert.is(helpers._actual.status(options), checks.status, 'status' + suffix);
}
if ('markup' in checks) {
assert.is(helpers._actual.markup(options), checks.markup, 'markup' + suffix);
}
if ('hints' in checks) {
var hintCheck = function(actualHints) {
assert.is(actualHints, checks.hints, 'hints' + suffix);
};
outstanding.push(helpers._actual.hints(options).then(hintCheck));
}
if ('predictions' in checks) {
var predictionsCheck = function(actualPredictions) {
helpers._arrayIs(actualPredictions,
checks.predictions,
'predictions' + suffix);
};
outstanding.push(helpers._actual.predictions(options).then(predictionsCheck));
}
if ('predictionsContains' in checks) {
var containsCheck = function(actualPredictions) {
checks.predictionsContains.forEach(function(prediction) {
var index = actualPredictions.indexOf(prediction);
assert.ok(index !== -1,
'predictionsContains:' + prediction + suffix);
});
};
outstanding.push(helpers._actual.predictions(options).then(containsCheck));
}
if ('unassigned' in checks) {
helpers._arrayIs(helpers._actual.unassigned(options),
checks.unassigned,
'unassigned' + suffix);
}
if ('tooltipState' in checks) {
if (options.isJsdom) {
assert.log('Skipped ' + name + '/tooltipState due to jsdom');
}
else {
assert.is(helpers._actual.tooltipState(options),
checks.tooltipState,
'tooltipState' + suffix);
}
}
if ('outputState' in checks) {
if (options.isJsdom) {
assert.log('Skipped ' + name + '/outputState due to jsdom');
}
else {
assert.is(helpers._actual.outputState(options),
checks.outputState,
'outputState' + suffix);
}
}
if ('options' in checks) {
helpers._arrayIs(helpers._actual.options(options),
checks.options,
'options' + suffix);
}
if ('error' in checks) {
assert.is(helpers._actual.message(options), checks.error, 'error' + suffix);
}
if (checks.args != null) {
var requisition = options.display.requisition;
Object.keys(checks.args).forEach(function(paramName) {
var check = checks.args[paramName];
var assignment;
if (paramName === 'command') {
assignment = requisition.commandAssignment;
}
else {
assignment = requisition.getAssignment(paramName);
}
if (assignment == null) {
assert.ok(false, 'Unknown arg: ' + paramName + suffix);
return;
}
if ('value' in check) {
assert.is(assignment.value,
check.value,
'arg.' + paramName + '.value' + suffix);
}
if ('name' in check) {
if (options.isJsdom) {
assert.log('Skipped arg.' + paramName + '.name due to jsdom');
}
else {
assert.is(assignment.value.name,
check.name,
'arg.' + paramName + '.name' + suffix);
}
}
if ('type' in check) {
assert.is(assignment.arg.type,
check.type,
'arg.' + paramName + '.type' + suffix);
}
if ('arg' in check) {
assert.is(assignment.arg.toString(),
check.arg,
'arg.' + paramName + '.arg' + suffix);
}
if ('status' in check) {
assert.is(assignment.getStatus().toString(),
check.status,
'arg.' + paramName + '.status' + suffix);
}
if ('message' in check) {
if (typeof check.message.test === 'function') {
assert.ok(check.message.test(assignment.getMessage()),
'arg.' + paramName + '.message' + suffix);
}
else {
assert.is(assignment.getMessage(),
check.message,
'arg.' + paramName + '.message' + suffix);
}
}
});
}
return util.all(outstanding).then(function() {
// Ensure the promise resolves to nothing
return undefined;
});
};
/**
* Helper for helpers.audit() to ensure that all the 'exec' properties work.
* See helpers.audit for more information.
* @param name The name to use in error messages
* @param expected See helpers.audit for a list of available exec checks
* @return A promise which resolves to undefined when the checks are complete
*/
helpers._exec = function(options, name, expected) {
if (expected == null) {
return Promise.resolve();
}
var output = options.display.requisition.exec({ hidden: true });
if ('completed' in expected) {
assert.is(output.completed,
expected.completed,
'output.completed false for: ' + name);
}
if (!options.window.document.createElement) {
assert.log('skipping output tests (missing doc.createElement) for ' + name);
return Promise.resolve();
}
if (!('output' in expected)) {
return Promise.resolve();
}
var deferred = Promise.defer();
var checkOutput = function() {
var div = options.window.document.createElement('div');
output.toDom(div);
var actualOutput = div.textContent.trim();
var doTest = function(match, against) {
if (!match.test(against)) {
assert.ok(false, 'html output for ' + name + ' against ' + match.source);
log('Actual textContent');
log(against);
}
};
if (typeof expected.output === 'string') {
assert.is(actualOutput,
expected.output,
'html output for ' + name);
}
else if (Array.isArray(expected.output)) {
expected.output.forEach(function(match) {
doTest(match, actualOutput);
});
}
else {
doTest(expected.output, actualOutput);
}
deferred.resolve();
};
if (output.completed !== false) {
checkOutput();
}
else {
var changed = function() {
if (output.completed !== false) {
checkOutput();
output.onChange.remove(changed);
}
};
output.onChange.add(changed);
}
return deferred.promise;
};
/**
* Helper to setup the test
*/
helpers._setup = function(options, name, action) {
if (typeof action === 'string') {
return helpers.setInput(options, action);
}
if (typeof action === 'function') {
return Promise.resolve(action());
}
return Promise.reject('setup must be a string or a function');
};
/**
* Helper to shutdown the test
*/
helpers._post = function(name, action) {
if (typeof action === 'function') {
return Promise.resolve(action());
}
return Promise.resolve(action);
};
/*
* We do some basic response time stats so we can see if we're getting slow
*/
var totalResponseTime = 0;
var averageOver = 0;
var maxResponseTime = 0;
var maxResponseCulprit = undefined;
/**
* Restart the stats collection process
*/
helpers.resetResponseTimes = function() {
totalResponseTime = 0;
averageOver = 0;
maxResponseTime = 0;
maxResponseCulprit = undefined;
};
/**
* Expose an average response time in milliseconds
*/
Object.defineProperty(helpers, 'averageResponseTime', {
get: function() {
return averageOver === 0 ?
undefined :
Math.round(100 * totalResponseTime / averageOver) / 100;
},
enumerable: true
});
/**
* Expose a maximum response time in milliseconds
*/
Object.defineProperty(helpers, 'maxResponseTime', {
get: function() { return Math.round(maxResponseTime * 100) / 100; },
enumerable: true
});
/**
* Expose the name of the test that provided the maximum response time
*/
Object.defineProperty(helpers, 'maxResponseCulprit', {
get: function() { return maxResponseCulprit; },
enumerable: true
});
/**
* A way of turning a set of tests into something more declarative, this helps
* to allow tests to be asynchronous.
* @param audits An array of objects each of which contains:
* - setup: string/function to be called to set the test up.
* If audit is a string then it is passed to helpers.setInput().
* If audit is a function then it is executed. The tests will wait while
* tests that return promises complete.
* - name: For debugging purposes. If name is undefined, and 'setup'
* is a string then the setup value will be used automatically
* - skipIf: A function to define if the test should be skipped. Useful for
* excluding tests from certain environments (e.g. jsdom, firefox, etc).
* The name of the test will be used in log messages noting the skip
* See helpers.reason for pre-defined skip functions. The skip function must
* be synchronous, and will be passed the test options object.
* - skipRemainingIf: A function to skip all the remaining audits in this set.
* See skipIf for details of how skip functions work.
* - check: Check data. Available checks:
* - input: The text displayed in the input field
* - cursor: The position of the start of the cursor
* - status: One of "VALID", "ERROR", "INCOMPLETE"
* - hints: The hint text, i.e. a concatenation of the directTabText, the
* emptyParameters and the arrowTabText. The text as inserted into the UI
* will include NBSP and Unicode RARR characters, these should be
* represented using normal space and '->' for the arrow
* - markup: What state should the error markup be in. e.g. "VVVIIIEEE"
* - args: Maps of checks to make against the arguments:
* - value: i.e. assignment.value (which ignores defaultValue)
* - type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
* Care should be taken with this since it's something of an
* implementation detail
* - arg: The toString value of the argument
* - status: i.e. assignment.getStatus
* - message: i.e. assignment.getMessage
* - name: For commands - checks assignment.value.name
* - exec: Object to indicate we should execute the command and check the
* results. Available checks:
* - output: A string, RegExp or array of RegExps to compare with the output
* If typeof output is a string then the output should be exactly equal
* to the given string. If the type of output is a RegExp or array of
* RegExps then the output should match all RegExps
* - completed: A boolean which declares that we should check to see if the
* command completed synchronously
* - post: Function to be called after the checks have been run
*/
helpers.audit = function(options, audits) {
checkOptions(options);
var skipReason = null;
return util.promiseEach(audits, function(audit) {
var name = audit.name;
if (name == null && typeof audit.setup === 'string') {
name = audit.setup;
}
if (assert.testLogging) {
log('- START \'' + name + '\' in ' + assert.currentTest);
}
if (audit.skipIf) {
var skip = (typeof audit.skipIf === 'function') ?
audit.skipIf(options) :
!!audit.skipIf;
if (skip) {
var reason = audit.skipIf.name ? 'due to ' + audit.skipIf.name : '';
assert.log('Skipped ' + name + ' ' + reason);
return Promise.resolve(undefined);
}
}
if (audit.skipRemainingIf) {
var skipRemainingIf = (typeof audit.skipRemainingIf === 'function') ?
audit.skipRemainingIf(options) :
!!audit.skipRemainingIf;
if (skipRemainingIf) {
skipReason = audit.skipRemainingIf.name ?
'due to ' + audit.skipRemainingIf.name :
'';
assert.log('Skipped ' + name + ' ' + skipReason);
return Promise.resolve(undefined);
}
}
if (skipReason != null) {
assert.log('Skipped ' + name + ' ' + skipReason);
return Promise.resolve(undefined);
}
var start = new Date().getTime();
var setupDone = helpers._setup(options, name, audit.setup);
return setupDone.then(function(chunkLen) {
if (typeof chunkLen !== 'number') {
chunkLen = 1;
}
var responseTime = (new Date().getTime() - start) / chunkLen;
totalResponseTime += responseTime;
if (responseTime > maxResponseTime) {
maxResponseTime = responseTime;
maxResponseCulprit = assert.currentTest + '/' + name;
}
averageOver++;
var checkDone = helpers._check(options, name, audit.check);
return checkDone.then(function() {
var execDone = helpers._exec(options, name, audit.exec);
return execDone.then(function() {
return helpers._post(name, audit.post).then(function() {
if (assert.testLogging) {
log('- END \'' + name + '\' in ' + assert.currentTest);
}
});
});
});
});
}).then(null, function(ex) {
console.error(ex.stack);
throw(ex);
});
};
/**
* Compare 2 arrays.
*/
helpers._arrayIs = function(actual, expected, message) {
assert.ok(Array.isArray(actual), 'actual is not an array: ' + message);
assert.ok(Array.isArray(expected), 'expected is not an array: ' + message);
if (!Array.isArray(actual) || !Array.isArray(expected)) {
return;
}
assert.is(actual.length, expected.length, 'array length: ' + message);
for (var i = 0; i < actual.length && i < expected.length; i++) {
assert.is(actual[i], expected[i], 'member[' + i + ']: ' + message);
}
};
/**
* A quick helper to log to the correct place
*/
function log(message) {
if (typeof info === 'function') {
info(message);
}
else {
console.log(message);
}
}
//});

Просмотреть файл

@ -5,6 +5,8 @@ let tempScope = {};
Cu.import("resource:///modules/devtools/Target.jsm", tempScope);
let TargetFactory = tempScope.TargetFactory;
let DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
function test() {
waitForExplicitFinish();
@ -23,10 +25,20 @@ function test() {
content.location = "http://mochi.test:8888/browser/browser/devtools/fontinspector/test/browser_fontinspector.html";
function setupTest() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
openFontInspector(toolbox.getCurrentPanel());
});
let rng = doc.createRange();
rng.selectNode(doc.body);
let fonts = DOMUtils.getUsedFontFaces(rng);
if (fonts.length != 2) {
// Fonts are not loaded yet.
// Let try again in a couple of milliseconds (hacky, but
// there's not better way to do it. See bug 835247).
setTimeout(setupTest, 500);
} else {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
openFontInspector(toolbox.getCurrentPanel());
});
}
}
function openFontInspector(aInspector) {

Просмотреть файл

@ -11,6 +11,11 @@ let toolbox, toolIDs, idIndex;
function test() {
waitForExplicitFinish();
if (window.navigator.oscpu.match(/osx 10\.8/i) || window.navigator.oscpu.match(/windows nt 5\.1/i)) {
info("Skipping Mac OSX 10.8 and Windows xp, see bug 838069");
finish();
return;
}
addTab("about:blank", function() {
toolIDs = [];
for (let [id, definition] of gDevTools._tools) {

Просмотреть файл

@ -7,114 +7,125 @@ const TEST_URI = "http://example.com/browser/browser/devtools/inspector/" +
"test/browser_inspector_cmd_inspect.html";
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testInspect ]);
}
function testInspect() {
helpers.setInput('inspect');
helpers.check({
input: 'inspect',
hints: ' <selector>',
markup: 'VVVVVVV',
status: 'ERROR',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect h1');
helpers.check({
input: 'inspect h1',
hints: '',
markup: 'VVVVVVVVII',
status: 'ERROR',
args: {
selector: { message: 'No matches' },
}
});
helpers.setInput('inspect span');
helpers.check({
input: 'inspect span',
hints: '',
markup: 'VVVVVVVVEEEE',
status: 'ERROR',
args: {
selector: { message: 'Too many matches (2)' },
}
});
helpers.setInput('inspect div');
helpers.check({
input: 'inspect div',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect .someclas');
helpers.check({
input: 'inspect .someclas',
hints: '',
markup: 'VVVVVVVVIIIIIIIII',
status: 'ERROR',
args: {
selector: { message: 'No matches' },
}
});
helpers.setInput('inspect .someclass');
helpers.check({
input: 'inspect .someclass',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect #someid');
helpers.check({
input: 'inspect #someid',
hints: '',
markup: 'VVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect button[disabled]');
helpers.check({
input: 'inspect button[disabled]',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect p>strong');
helpers.check({
input: 'inspect p>strong',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
});
helpers.setInput('inspect :root');
helpers.check({
input: 'inspect :root',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
});
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.audit(options, [
{
setup: "inspect",
check: {
input: 'inspect',
hints: ' <selector>',
markup: 'VVVVVVV',
status: 'ERROR',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect h1",
check: {
input: 'inspect h1',
hints: '',
markup: 'VVVVVVVVII',
status: 'ERROR',
args: {
selector: { message: 'No matches' },
}
},
},
{
setup: "inspect span",
check: {
input: 'inspect span',
hints: '',
markup: 'VVVVVVVVEEEE',
status: 'ERROR',
args: {
selector: { message: 'Too many matches (2)' },
}
},
},
{
setup: "inspect div",
check: {
input: 'inspect div',
hints: '',
markup: 'VVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect .someclas",
check: {
input: 'inspect .someclas',
hints: '',
markup: 'VVVVVVVVIIIIIIIII',
status: 'ERROR',
args: {
selector: { message: 'No matches' },
}
},
},
{
setup: "inspect .someclass",
check: {
input: 'inspect .someclass',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect #someid",
check: {
input: 'inspect #someid',
hints: '',
markup: 'VVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect button[disabled]",
check: {
input: 'inspect button[disabled]',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect p>strong",
check: {
input: 'inspect p>strong',
hints: '',
markup: 'VVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
selector: { message: '' },
}
},
},
{
setup: "inspect :root",
check: {
input: 'inspect :root',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
},
},
]);
}).then(finish);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2,85 +2,106 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
DeveloperToolbarTest.test("about:blank", [ GAT_test ]);
}
function isOpen() {
return !!gBrowser.selectedTab.__responsiveUI;
}
function isClosed() {
return !isOpen();
}
function GAT_test() {
helpers.setInput('resize toggle');
helpers.check({
input: 'resize toggle',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
helpers.setInput('resize toggle');
helpers.check({
input: 'resize toggle',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
helpers.setInput('resize on');
helpers.check({
input: 'resize on',
hints: '',
markup: 'VVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
helpers.setInput('resize off');
helpers.check({
input: 'resize off',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
helpers.setInput('resize to 400 400');
helpers.check({
input: 'resize to 400 400',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
width: { value: 400 },
height: { value: 400 },
}
});
DeveloperToolbarTest.exec();
ok(isOpen(), "responsive mode is open");
helpers.setInput('resize off');
helpers.check({
input: 'resize off',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
});
DeveloperToolbarTest.exec();
ok(isClosed(), "responsive mode is closed");
function isOpen() {
return !!gBrowser.selectedTab.__responsiveUI;
}
helpers.addTabWithToolbar("about:blank", function(options) {
return helpers.audit(options, [
{
setup: "resize toggle",
check: {
input: 'resize toggle',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ""
},
post: function() {
ok(isOpen(), "responsive mode is open");
},
},
{
setup: "resize toggle",
check: {
input: 'resize toggle',
hints: '',
markup: 'VVVVVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ""
},
post: function() {
ok(!isOpen(), "responsive mode is closed");
},
},
{
setup: "resize on",
check: {
input: 'resize on',
hints: '',
markup: 'VVVVVVVVV',
status: 'VALID'
},
exec: {
output: ""
},
post: function() {
ok(isOpen(), "responsive mode is open");
},
},
{
setup: "resize off",
check: {
input: 'resize off',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ""
},
post: function() {
ok(!isOpen(), "responsive mode is closed");
},
},
{
setup: "resize to 400 400",
check: {
input: 'resize to 400 400',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
width: { value: 400 },
height: { value: 400 },
}
},
exec: {
output: ""
},
post: function() {
ok(isOpen(), "responsive mode is open");
},
},
{
setup: "resize off",
check: {
input: 'resize off',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: ""
},
post: function() {
ok(!isOpen(), "responsive mode is closed");
},
},
]);
}).then(finish);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -30,6 +30,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "PageErrorListener",
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "TargetFactory",
"resource:///modules/devtools/Target.jsm");
XPCOMUtils.defineLazyGetter(this, "prefBranch", function() {
let prefService = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
@ -44,7 +47,7 @@ XPCOMUtils.defineLazyGetter(this, "toolboxStrings", function () {
/**
* A collection of utilities to help working with commands
*/
this.CommandUtils = {
let CommandUtils = {
/**
* Read a toolbarSpec from preferences
* @param aPref The name of the preference to read
@ -136,9 +139,35 @@ this.CommandUtils = {
requisition.update('');
return reply;
}
},
/**
* A helper function to create the environment object that is passed to
* GCLI commands.
*/
createEnvironment: function(chromeDocument, contentDocument) {
let environment = {
chromeDocument: chromeDocument,
contentDocument: contentDocument, // Use of contentDocument is deprecated
document: contentDocument,
window: contentDocument.defaultView
};
Object.defineProperty(environment, "target", {
get: function() {
let tab = chromeDocument.defaultView.getBrowser().selectedTab;
return TargetFactory.forTab(tab);
},
enumerable: true
});
return environment;
},
};
this.CommandUtils = CommandUtils;
/**
* Due to a number of panel bugs we need a way to check if we are running on
* Linux. See the comments for TooltipPanel and OutputPanel for further details.
@ -326,18 +355,12 @@ DeveloperToolbar.prototype._onload = function DT_onload(aFocus)
contentDocument: contentDocument,
chromeDocument: this._doc,
chromeWindow: this._chromeWindow,
hintElement: this.tooltipPanel.hintElement,
inputElement: this._input,
completeElement: this._doc.querySelector(".gclitoolbar-complete-node"),
backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
outputDocument: this.outputPanel.document,
environment: {
chromeDocument: this._doc,
contentDocument: contentDocument
},
environment: CommandUtils.createEnvironment(this._doc, contentDocument),
tooltipClass: 'gcliterm-tooltip',
eval: null,
scratchpad: null
@ -530,10 +553,7 @@ DeveloperToolbar.prototype.handleEvent = function DT_handleEvent(aEvent)
this.display.reattach({
contentDocument: contentDocument,
chromeWindow: this._chromeWindow,
environment: {
chromeDocument: this._doc,
contentDocument: contentDocument
},
environment: CommandUtils.createEnvironment(this._doc, contentDocument),
});
if (aEvent.type == "TabSelect") {

Просмотреть файл

@ -14,19 +14,18 @@
* limitations under the License.
*/
this.EXPORTED_SYMBOLS = [ "template" ];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
this.EXPORTED_SYMBOLS = [ "Templater", "template" ];
Components.utils.import("resource://gre/modules/Services.jsm");
const Node = Components.interfaces.nsIDOMNode;
// WARNING: do not 'use_strict' without reading the notes in _envEval();
/**
* For full documentation, see:
* https://github.com/mozilla/domtemplate/blob/master/README.md
*/
// WARNING: do not 'use_strict' without reading the notes in _envEval();
/**
* Begin a new templating process.
* @param node A DOM element or string referring to an element's id
@ -44,7 +43,7 @@ const Node = Components.interfaces.nsIDOMNode;
* convert null/undefined to ''. By setting blankNullUndefined:true, this
* conversion is handled by DOMTemplate
*/
this.template = function template(node, data, options) {
function template(node, data, options) {
var template = new Templater(options || {});
template.processNode(node, data);
return template;
@ -54,7 +53,7 @@ this.template = function template(node, data, options) {
* Construct a Templater object. Use template() in preference to this ctor.
* @deprecated Use template(node, data, options);
*/
this.Templater = function Templater(options) {
function Templater(options) {
if (options == null) {
options = { allowEval: true };
}
@ -132,6 +131,7 @@ Templater.prototype.processNode = function(node, data) {
for (var i = 0; i < attrs.length; i++) {
var value = attrs[i].value;
var name = attrs[i].name;
this.stack.push(name);
try {
if (name === 'save') {
@ -139,39 +139,62 @@ Templater.prototype.processNode = function(node, data) {
value = this._stripBraces(value);
this._property(value, data, node);
node.removeAttribute('save');
} else if (name.substring(0, 2) === 'on') {
// Event registration relies on property doing a bind
value = this._stripBraces(value);
var func = this._property(value, data);
if (typeof func !== 'function') {
this._handleError('Expected ' + value +
' to resolve to a function, but got ' + typeof func);
}
node.removeAttribute(name);
var capture = node.hasAttribute('capture' + name.substring(2));
node.addEventListener(name.substring(2), func, capture);
if (capture) {
node.removeAttribute('capture' + name.substring(2));
}
} else {
// Replace references in all other attributes
var newValue = value.replace(this._templateRegion, function(path) {
var insert = this._envEval(path.slice(2, -1), data, value);
if (this.options.blankNullUndefined && insert == null) {
insert = '';
}
else if (name.substring(0, 2) === 'on') {
// If this attribute value contains only an expression
if (value.substring(0, 2) === '${' && value.slice(-1) === '}' &&
value.indexOf('${', 2) === -1) {
value = this._stripBraces(value);
var func = this._property(value, data);
if (typeof func === 'function') {
node.removeAttribute(name);
var capture = node.hasAttribute('capture' + name.substring(2));
node.addEventListener(name.substring(2), func, capture);
if (capture) {
node.removeAttribute('capture' + name.substring(2));
}
}
return insert;
}.bind(this));
else {
// Attribute value is not a function - use as a DOM-L0 string
node.setAttribute(name, func);
}
}
else {
// Attribute value is not a single expression use as DOM-L0
node.setAttribute(name, this._processString(value, data));
}
}
else {
node.removeAttribute(name);
// Remove '_' prefix of attribute names so the DOM won't try
// to use them before we've processed the template
if (name.charAt(0) === '_') {
node.removeAttribute(name);
node.setAttribute(name.substring(1), newValue);
} else if (value !== newValue) {
attrs[i].value = newValue;
name = name.substring(1);
}
// Async attributes can only work if the whole attribute is async
var replacement;
if (value.indexOf('${') === 0 && value.charAt(value.length - 1) === '}') {
replacement = this._envEval(value.slice(2, -1), data, value);
if (replacement && typeof replacement.then === 'function') {
node.setAttribute(name, '');
replacement.then(function(newValue) {
node.setAttribute(name, newValue);
}.bind(this)).then(null, console.error);
}
else {
if (this.options.blankNullUndefined && replacement == null) {
replacement = '';
}
node.setAttribute(name, replacement);
}
}
else {
node.setAttribute(name, this._processString(value, data));
}
}
} finally {
}
finally {
this.stack.pop();
}
}
@ -187,7 +210,8 @@ Templater.prototype.processNode = function(node, data) {
if (node.nodeType === 3 /*Node.TEXT_NODE*/) {
this._processTextNode(node, data);
}
} finally {
}
finally {
if (pushedNode) {
data.__element = this.nodes.pop();
}
@ -195,6 +219,16 @@ Templater.prototype.processNode = function(node, data) {
}
};
/**
* Handle attribute values where the output can only be a string
*/
Templater.prototype._processString = function(value, data) {
return value.replace(this._templateRegion, function(path) {
var insert = this._envEval(path.slice(2, -1), data, value);
return this.options.blankNullUndefined && insert == null ? '' : insert;
}.bind(this));
};
/**
* Handle <x if="${...}">
* @param node An element with an 'if' attribute
@ -210,7 +244,8 @@ Templater.prototype._processIf = function(node, data) {
try {
var reply = this._envEval(value, data, originalValue);
recurse = !!reply;
} catch (ex) {
}
catch (ex) {
this._handleError('Error with \'' + value + '\'', ex);
recurse = false;
}
@ -219,7 +254,8 @@ Templater.prototype._processIf = function(node, data) {
}
node.removeAttribute('if');
return recurse;
} finally {
}
finally {
this.stack.pop();
}
};
@ -244,7 +280,8 @@ Templater.prototype._processForEach = function(node, data) {
if (value.charAt(0) === '$') {
// No custom loop variable name. Use the default: 'param'
value = this._stripBraces(value);
} else {
}
else {
// Extract the loop variable name from 'NAME in ${ARRAY}'
var nameArr = value.split(' in ');
paramName = nameArr[0].trim();
@ -257,10 +294,12 @@ Templater.prototype._processForEach = function(node, data) {
this._processForEachLoop(reply, node, siblingNode, data, paramName);
}.bind(this));
node.parentNode.removeChild(node);
} catch (ex) {
}
catch (ex) {
this._handleError('Error with \'' + value + '\'', ex);
}
} finally {
}
finally {
this.stack.pop();
}
};
@ -281,7 +320,8 @@ Templater.prototype._processForEachLoop = function(set, template, sibling, data,
set.forEach(function(member, i) {
this._processForEachMember(member, template, sibling, data, paramName, '' + i);
}, this);
} else {
}
else {
for (var member in set) {
if (set.hasOwnProperty(member)) {
this._processForEachMember(member, template, sibling, data, paramName, member);
@ -307,21 +347,25 @@ Templater.prototype._processForEachMember = function(member, template, siblingNo
try {
this._handleAsync(member, siblingNode, function(reply, node) {
data[paramName] = reply;
if (template.nodeName.toLowerCase() === 'loop') {
for (var i = 0; i < template.childNodes.length; i++) {
var clone = template.childNodes[i].cloneNode(true);
if (node.parentNode != null) {
if (template.nodeName.toLowerCase() === 'loop') {
for (var i = 0; i < template.childNodes.length; i++) {
var clone = template.childNodes[i].cloneNode(true);
node.parentNode.insertBefore(clone, node);
this.processNode(clone, data);
}
}
else {
var clone = template.cloneNode(true);
clone.removeAttribute('foreach');
node.parentNode.insertBefore(clone, node);
this.processNode(clone, data);
}
} else {
var clone = template.cloneNode(true);
clone.removeAttribute('foreach');
node.parentNode.insertBefore(clone, node);
this.processNode(clone, data);
}
delete data[paramName];
}.bind(this));
} finally {
}
finally {
this.stack.pop();
}
};
@ -364,7 +408,8 @@ Templater.prototype._processTextNode = function(node, data) {
// i.e. if (reply instanceof Element) { ...
reply = this._maybeImportNode(reply, doc);
siblingNode.parentNode.insertBefore(reply, siblingNode);
} else if (typeof reply.item === 'function' && reply.length) {
}
else if (typeof reply.item === 'function' && reply.length) {
// NodeLists can be live, in which case _maybeImportNode can
// remove them from the document, and thus the NodeList, which in
// turn breaks iteration. So first we clone the list
@ -379,7 +424,6 @@ Templater.prototype._processTextNode = function(node, data) {
reply = doc.createTextNode(reply.toString());
siblingNode.parentNode.insertBefore(reply, siblingNode);
}
}.bind(this));
}, this);
node.parentNode.removeChild(node);
@ -413,8 +457,12 @@ Templater.prototype._handleAsync = function(thing, siblingNode, inserter) {
siblingNode.parentNode.insertBefore(tempNode, siblingNode);
thing.then(function(delayed) {
inserter(delayed, tempNode);
tempNode.parentNode.removeChild(tempNode);
}.bind(this));
if (tempNode.parentNode != null) {
tempNode.parentNode.removeChild(tempNode);
}
}.bind(this)).then(null, function(error) {
console.error(error.stack);
});
}
else {
inserter(thing, siblingNode);
@ -471,7 +519,8 @@ Templater.prototype._property = function(path, data, newValue) {
return null;
}
return this._property(path.slice(1), value, newValue);
} catch (ex) {
}
catch (ex) {
this._handleError('Path error with \'' + path + '\'', ex);
return '${' + path + '}';
}
@ -495,7 +544,8 @@ Templater.prototype._envEval = function(script, data, frame) {
this.stack.push(frame.replace(/\s+/g, ' '));
if (this._isPropertyScript.test(script)) {
return this._property(script, data);
} else {
}
else {
if (!this.options.allowEval) {
this._handleError('allowEval is not set, however \'' + script + '\'' +
' can not be resolved using a simple property path.');
@ -505,10 +555,12 @@ Templater.prototype._envEval = function(script, data, frame) {
return eval(script);
}
}
} catch (ex) {
}
catch (ex) {
this._handleError('Template error evaluating \'' + script + '\'', ex);
return '${' + script + '}';
} finally {
}
finally {
this.stack.pop();
}
};
@ -526,12 +578,17 @@ Templater.prototype._handleError = function(message, ex) {
}
};
/**
* A generic way of reporting errors, for easy overloading in different
* environments.
* @param message the error message to report.
*/
Templater.prototype._logError = function(message) {
Services.console.logStringMessage(message);
console.log(message);
};
//
this.template = template;
//
// });

Просмотреть файл

@ -23,7 +23,6 @@ MOCHITEST_BROWSER_FILES = \
browser_layoutHelpers.js \
browser_eventemitter_basic.js \
head.js \
helpers.js \
leakhunt.js \
$(NULL)

Просмотреть файл

@ -9,12 +9,13 @@
* We should endevour to keep the source in sync.
*/
var imports = {};
Cu.import("resource:///modules/devtools/Templater.jsm", imports);
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", imports);
var Promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
var template = Cu.import("resource:///modules/devtools/Templater.jsm", {}).template;
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html";
function test() {
addTab("http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html", function() {
addTab(TEST_URI, function() {
info("Starting DOM Templater Tests");
runTest(0);
});
@ -29,13 +30,14 @@ function runTest(index) {
holder.innerHTML = options.template;
info('Running ' + options.name);
imports.template(holder, options.data, options.options);
template(holder, options.data, options.options);
if (typeof options.result == 'string') {
is(holder.innerHTML, options.result, options.name);
}
else {
ok(holder.innerHTML.match(options.result), options.name);
ok(holder.innerHTML.match(options.result) != null,
options.name + ' result=\'' + holder.innerHTML + '\'');
}
if (options.also) {
@ -278,7 +280,7 @@ var tests = [
];
function delayReply(data) {
var d = imports.Promise.defer();
var d = Promise.defer();
executeSoon(function() {
d.resolve(data);
});

Просмотреть файл

@ -3,12 +3,6 @@
// Tests that the developer toolbar works properly
let imported = {};
Components.utils.import("resource:///modules/HUDService.jsm", imported);
registerCleanupFunction(function() {
imported = {};
});
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_toolbar_basic.html";
function test() {
@ -78,13 +72,3 @@ function checkReClosed() {
finish();
}
//------------------------------------------------------------------------------
function oneTimeObserve(name, callback) {
var func = function() {
Services.obs.removeObserver(func, name);
callback();
};
Services.obs.addObserver(func, name, false);
}

Просмотреть файл

@ -6,12 +6,19 @@
const TEST_URI = "data:text/html;charset=utf-8,<p>Tooltip Tests</p>";
function test() {
DeveloperToolbarTest.test(TEST_URI, function(browser, tab) {
runTest();
finish();
addTab(TEST_URI, function(browser, tab) {
info("Starting browser_toolbar_tooltip.js");
openTest();
});
}
function openTest() {
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible in runTest");
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW, catchFail(runTest));
document.getElementById("Tools:DevToolbar").doCommand();
}
function runTest() {
let tooltipPanel = DeveloperToolbar.tooltipPanel;
@ -37,6 +44,8 @@ function runTest() {
is(tooltipPanel._dimensions.start, 0,
'search param start, when cursor at start');
ok(getLeftMargin() > 9, 'tooltip offset, when cursor at start')
finish();
}
function getLeftMargin() {

Просмотреть файл

@ -14,11 +14,7 @@ function test() {
Components.utils.import("resource:///modules/devtools/gDevTools.jsm", imported);
let gDevTools = imported.gDevTools;
Components.utils.import("resource:///modules/devtools/Target.jsm", imported);
let TargetFactory = imported.TargetFactory;
let webconsole = document.getElementById("developer-toolbar-toolbox-button");
let toolbar = document.getElementById("Tools:DevToolbar");
let tab1, tab2;
Services.prefs.setBoolPref("javascript.options.strict", true);
@ -27,11 +23,14 @@ function test() {
tab1 = tab;
ignoreAllUncaughtExceptions(false);
ok(!DeveloperToolbar.visible, "DeveloperToolbar is not visible");
expectUncaughtException();
oneTimeObserve(DeveloperToolbar.NOTIFICATIONS.SHOW, onOpenToolbar);
toolbar.doCommand();
if (!DeveloperToolbar.visible) {
DeveloperToolbar.show(true, onOpenToolbar);
}
else {
onOpenToolbar();
}
}
ignoreAllUncaughtExceptions();

Просмотреть файл

@ -2,21 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let console = (function() {
let tempScope = {};
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
return tempScope.console;
})();
let TargetFactory = (function() {
let tempScope = {};
Components.utils.import("resource:///modules/devtools/Target.jsm", tempScope);
return tempScope.TargetFactory;
})();
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "/helpers.js", this);
let TargetFactory = (Cu.import("resource:///modules/devtools/Target.jsm", {})).TargetFactory;
/**
* Open a new tab at a URL and call a callback on load
@ -124,3 +110,11 @@ function waitForValue(aOptions)
wait(aOptions.validator, aOptions.success, aOptions.failure);
}
function oneTimeObserve(name, callback) {
var func = function() {
Services.obs.removeObserver(func, name);
callback();
};
Services.obs.addObserver(func, name, false);
}

Просмотреть файл

@ -1,881 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*
* DO NOT ALTER THIS FILE WITHOUT KEEPING IT IN SYNC WITH THE OTHER COPIES
* OF THIS FILE.
*
* UNAUTHORIZED ALTERATION WILL RESULT IN THE ALTEREE BEING SENT TO SIT ON
* THE NAUGHTY STEP.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* FOR A LONG TIME.
*
*/
/*
* Use as a JSM
* ------------
* helpers._createDebugCheck() and maybe other functions in this file can be
* useful at runtime, so it is possible to use helpers.js as a JSM.
* Copy commandline/test/helpers.js to shared/helpers.jsm, and then add to
* DeveloperToolbar.jsm the following:
*
* XPCOMUtils.defineLazyModuleGetter(this, "helpers",
* "resource:///modules/devtools/helpers.jsm");
*
* At the bottom of DeveloperToolbar.prototype._onload add this:
*
* var options = { display: this.display };
* this._input.onkeypress = function(ev) {
* helpers.setup(options);
* dump(helpers._createDebugCheck() + '\n\n');
* };
*
* Now GCLI will emit output on every keypress that both explains the state
* of GCLI and can be run as a test case.
*/
this.EXPORTED_SYMBOLS = [ 'helpers' ];
var test = { };
/**
* Various functions for testing DeveloperToolbar.
* Parts of this code exist in:
* - browser/devtools/commandline/test/head.js
* - browser/devtools/shared/test/head.js
*/
let DeveloperToolbarTest = { };
/**
* Paranoid DeveloperToolbar.show();
*/
DeveloperToolbarTest.show = function DTT_show(aCallback) {
if (DeveloperToolbar.visible) {
ok(false, "DeveloperToolbar.visible at start of openDeveloperToolbar");
}
else {
DeveloperToolbar.show(true, aCallback);
}
};
/**
* Paranoid DeveloperToolbar.hide();
*/
DeveloperToolbarTest.hide = function DTT_hide() {
if (!DeveloperToolbar.visible) {
ok(false, "!DeveloperToolbar.visible at start of closeDeveloperToolbar");
}
else {
DeveloperToolbar.display.inputter.setInput("");
DeveloperToolbar.hide();
}
};
/**
* check() is the new status. Similar API except that it doesn't attempt to
* alter the display/requisition at all, and it makes extra checks.
* Test inputs
* typed: The text to type at the input
* Available checks:
* input: The text displayed in the input field
* cursor: The position of the start of the cursor
* status: One of "VALID", "ERROR", "INCOMPLETE"
* emptyParameters: Array of parameters still to type. e.g. [ "<message>" ]
* directTabText: Simple completion text
* arrowTabText: When the completion is not an extension (without arrow)
* markup: What state should the error markup be in. e.g. "VVVIIIEEE"
* args: Maps of checks to make against the arguments:
* value: i.e. assignment.value (which ignores defaultValue)
* type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
* Care should be taken with this since it's something of an
* implementation detail
* arg: The toString value of the argument
* status: i.e. assignment.getStatus
* message: i.e. assignment.getMessage
* name: For commands - checks assignment.value.name
*/
DeveloperToolbarTest.checkInputStatus = function DTT_checkInputStatus(checks) {
if (!checks.emptyParameters) {
checks.emptyParameters = [];
}
if (!checks.directTabText) {
checks.directTabText = '';
}
if (!checks.arrowTabText) {
checks.arrowTabText = '';
}
var display = DeveloperToolbar.display;
if (checks.typed) {
info('Starting tests for ' + checks.typed);
display.inputter.setInput(checks.typed);
}
else {
ok(false, "Missing typed for " + JSON.stringify(checks));
return;
}
if (checks.cursor) {
display.inputter.setCursor(checks.cursor)
}
var cursor = checks.cursor ? checks.cursor.start : checks.typed.length;
var requisition = display.requisition;
var completer = display.completer;
var actual = completer._getCompleterTemplateData();
/*
if (checks.input) {
is(display.inputter.element.value,
checks.input,
'input');
}
if (checks.cursor) {
is(display.inputter.element.selectionStart,
checks.cursor,
'cursor');
}
*/
if (checks.status) {
is(requisition.getStatus().toString(),
checks.status,
'status');
}
if (checks.markup) {
var statusMarkup = requisition.getInputStatusMarkup(cursor);
var actualMarkup = statusMarkup.map(function(s) {
return Array(s.string.length + 1).join(s.status.toString()[0]);
}).join('');
is(checks.markup,
actualMarkup,
'markup');
}
if (checks.emptyParameters) {
var actualParams = actual.emptyParameters;
is(actualParams.length,
checks.emptyParameters.length,
'emptyParameters.length');
if (actualParams.length === checks.emptyParameters.length) {
for (var i = 0; i < actualParams.length; i++) {
is(actualParams[i].replace(/\u00a0/g, ' '),
checks.emptyParameters[i],
'emptyParameters[' + i + ']');
}
}
else {
info('Expected: [ \"' + actualParams.join('", "') + '" ]');
}
}
if (checks.directTabText) {
is(actual.directTabText,
checks.directTabText,
'directTabText');
}
if (checks.arrowTabText) {
is(actual.arrowTabText,
' \u00a0\u21E5 ' + checks.arrowTabText,
'arrowTabText');
}
if (checks.args) {
Object.keys(checks.args).forEach(function(paramName) {
var check = checks.args[paramName];
var assignment;
if (paramName === 'command') {
assignment = requisition.commandAssignment;
}
else {
assignment = requisition.getAssignment(paramName);
}
if (assignment == null) {
ok(false, 'Unknown parameter: ' + paramName);
return;
}
if (check.value) {
is(assignment.value,
check.value,
'checkStatus value for ' + paramName);
}
if (check.name) {
is(assignment.value.name,
check.name,
'checkStatus name for ' + paramName);
}
if (check.type) {
is(assignment.arg.type,
check.type,
'checkStatus type for ' + paramName);
}
if (check.arg) {
is(assignment.arg.toString(),
check.arg,
'checkStatus arg for ' + paramName);
}
if (check.status) {
is(assignment.getStatus().toString(),
check.status,
'checkStatus status for ' + paramName);
}
if (check.message) {
is(assignment.getMessage(),
check.message,
'checkStatus message for ' + paramName);
}
});
}
};
/**
* Execute a command:
*
* DeveloperToolbarTest.exec({
* // Test inputs
* typed: "echo hi", // Optional, uses existing if undefined
*
* // Thing to check
* args: { message: "hi" }, // Check that the args were understood properly
* outputMatch: /^hi$/, // RegExp to test against textContent of output
* // (can also be array of RegExps)
* blankOutput: true, // Special checks when there is no output
* });
*/
DeveloperToolbarTest.exec = function DTT_exec(tests) {
tests = tests || {};
if (tests.typed) {
DeveloperToolbar.display.inputter.setInput(tests.typed);
}
let typed = DeveloperToolbar.display.inputter.getInputState().typed;
let output = DeveloperToolbar.display.requisition.exec();
is(typed, output.typed, 'output.command for: ' + typed);
if (tests.completed !== false) {
ok(output.completed, 'output.completed false for: ' + typed);
}
else {
// It is actually an error if we say something is async and it turns
// out not to be? For now we're saying 'no'
// ok(!output.completed, 'output.completed true for: ' + typed);
}
if (tests.args != null) {
is(Object.keys(tests.args).length, Object.keys(output.args).length,
'arg count for ' + typed);
Object.keys(output.args).forEach(function(arg) {
let expectedArg = tests.args[arg];
let actualArg = output.args[arg];
if (typeof expectedArg === 'function') {
ok(expectedArg(actualArg), 'failed test func. ' + typed + '/' + arg);
}
else {
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
ok(false, 'actual is not an array. ' + typed + '/' + arg);
return;
}
is(expectedArg.length, actualArg.length,
'array length: ' + typed + '/' + arg);
for (let i = 0; i < expectedArg.length; i++) {
is(expectedArg[i], actualArg[i],
'member: "' + typed + '/' + arg + '/' + i);
}
}
else {
is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
}
}
});
}
let displayed = DeveloperToolbar.outputPanel._div.textContent;
if (tests.outputMatch) {
var doTest = function(match, against) {
if (!match.test(against)) {
ok(false, "html output for " + typed + " against " + match.source +
" (textContent sent to info)");
info("Actual textContent");
info(against);
}
}
if (Array.isArray(tests.outputMatch)) {
tests.outputMatch.forEach(function(match) {
doTest(match, displayed);
});
}
else {
doTest(tests.outputMatch, displayed);
}
}
if (tests.blankOutput != null) {
if (!/^$/.test(displayed)) {
ok(false, "html output for " + typed + " (textContent sent to info)");
info("Actual textContent");
info(displayed);
}
}
};
/**
* Quick wrapper around the things you need to do to run DeveloperToolbar
* command tests:
* - Set the pref 'devtools.toolbar.enabled' to true
* - Add a tab pointing at |uri|
* - Open the DeveloperToolbar
* - Register a cleanup function to undo the above
* - Run the tests
*
* @param uri The uri of a page to load. Can be 'about:blank' or 'data:...'
* @param target Either a function or array of functions containing the tests
* to run. If an array of test function is passed then we will clear up after
* the tests have completed. If a single test function is passed then this
* function should arrange for 'finish()' to be called on completion.
*/
DeveloperToolbarTest.test = function DTT_test(uri, target) {
let menuItem = document.getElementById("menu_devToolbar");
let command = document.getElementById("Tools:DevToolbar");
let appMenuItem = document.getElementById("appmenu_devToolbar");
registerCleanupFunction(function() {
DeveloperToolbarTest.hide();
// a.k.a Services.prefs.clearUserPref("devtools.toolbar.enabled");
if (menuItem) {
menuItem.hidden = true;
}
if (command) {
command.setAttribute("disabled", "true");
}
if (appMenuItem) {
appMenuItem.hidden = true;
}
// leakHunt({ DeveloperToolbar: DeveloperToolbar });
});
// a.k.a: Services.prefs.setBoolPref("devtools.toolbar.enabled", true);
if (menuItem) {
menuItem.hidden = false;
}
if (command) {
command.removeAttribute("disabled");
}
if (appMenuItem) {
appMenuItem.hidden = false;
}
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = uri;
let tab = gBrowser.selectedTab;
let browser = gBrowser.getBrowserForTab(tab);
var onTabLoad = function() {
browser.removeEventListener("load", onTabLoad, true);
DeveloperToolbarTest.show(function() {
if (helpers) {
helpers.setup({ display: DeveloperToolbar.display });
}
if (Array.isArray(target)) {
try {
target.forEach(function(func) {
func(browser, tab);
})
}
finally {
DeveloperToolbarTest._checkFinish();
}
}
else {
try {
target(browser, tab);
}
catch (ex) {
ok(false, "" + ex);
DeveloperToolbarTest._finish();
throw ex;
}
}
});
}
browser.addEventListener("load", onTabLoad, true);
};
DeveloperToolbarTest._outstanding = [];
DeveloperToolbarTest._checkFinish = function() {
info('_checkFinish. ' + DeveloperToolbarTest._outstanding.length + ' outstanding');
if (DeveloperToolbarTest._outstanding.length == 0) {
DeveloperToolbarTest._finish();
}
}
DeveloperToolbarTest._finish = function() {
info('Finish');
DeveloperToolbarTest.closeAllTabs();
finish();
}
DeveloperToolbarTest.checkCalled = function(aFunc, aScope) {
var todo = function() {
var reply = aFunc.apply(aScope, arguments);
DeveloperToolbarTest._outstanding = DeveloperToolbarTest._outstanding.filter(function(aJob) {
return aJob != todo;
});
DeveloperToolbarTest._checkFinish();
return reply;
}
DeveloperToolbarTest._outstanding.push(todo);
return todo;
};
DeveloperToolbarTest.checkNotCalled = function(aMsg, aFunc, aScope) {
return function() {
ok(false, aMsg);
return aFunc.apply(aScope, arguments);
}
};
/**
*
*/
DeveloperToolbarTest.closeAllTabs = function() {
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
};
///////////////////////////////////////////////////////////////////////////////
this.helpers = {};
helpers._display = undefined;
helpers.setup = function(options) {
helpers._display = options.display;
if (typeof ok !== 'undefined') {
test.ok = ok;
test.is = is;
test.log = info;
}
};
helpers.shutdown = function(options) {
helpers._display = undefined;
};
/**
* Various functions to return the actual state of the command line
*/
helpers._actual = {
input: function() {
return helpers._display.inputter.element.value;
},
hints: function() {
var templateData = helpers._display.completer._getCompleterTemplateData();
var actualHints = templateData.directTabText +
templateData.emptyParameters.join('') +
templateData.arrowTabText;
return actualHints.replace(/\u00a0/g, ' ')
.replace(/\u21E5/, '->')
.replace(/ $/, '');
},
markup: function() {
var cursor = helpers._display.inputter.element.selectionStart;
var statusMarkup = helpers._display.requisition.getInputStatusMarkup(cursor);
return statusMarkup.map(function(s) {
return Array(s.string.length + 1).join(s.status.toString()[0]);
}).join('');
},
cursor: function() {
return helpers._display.inputter.element.selectionStart;
},
current: function() {
return helpers._display.requisition.getAssignmentAt(helpers._actual.cursor()).param.name;
},
status: function() {
return helpers._display.requisition.getStatus().toString();
},
outputState: function() {
var outputData = helpers._display.focusManager._shouldShowOutput();
return outputData.visible + ':' + outputData.reason;
},
tooltipState: function() {
var tooltipData = helpers._display.focusManager._shouldShowTooltip();
return tooltipData.visible + ':' + tooltipData.reason;
}
};
helpers._directToString = [ 'boolean', 'undefined', 'number' ];
helpers._createDebugCheck = function() {
var requisition = helpers._display.requisition;
var command = requisition.commandAssignment.value;
var input = helpers._actual.input();
var padding = Array(input.length + 1).join(' ');
var output = '';
output += 'helpers.setInput(\'' + input + '\');\n';
output += 'helpers.check({\n';
output += ' input: \'' + input + '\',\n';
output += ' hints: ' + padding + '\'' + helpers._actual.hints() + '\',\n';
output += ' markup: \'' + helpers._actual.markup() + '\',\n';
output += ' cursor: ' + helpers._actual.cursor() + ',\n';
output += ' current: \'' + helpers._actual.current() + '\',\n';
output += ' status: \'' + helpers._actual.status() + '\',\n';
output += ' outputState: \'' + helpers._actual.outputState() + '\',\n';
if (command) {
output += ' tooltipState: \'' + helpers._actual.tooltipState() + '\',\n';
output += ' args: {\n';
output += ' command: { name: \'' + command.name + '\' },\n';
requisition.getAssignments().forEach(function(assignment) {
output += ' ' + assignment.param.name + ': { ';
if (typeof assignment.value === 'string') {
output += 'value: \'' + assignment.value + '\', ';
}
else if (helpers._directToString.indexOf(typeof assignment.value) !== -1) {
output += 'value: ' + assignment.value + ', ';
}
else if (assignment.value === null) {
output += 'value: ' + assignment.value + ', ';
}
else {
output += '/*value:' + assignment.value + ',*/ ';
}
output += 'arg: \'' + assignment.arg + '\', ';
output += 'status: \'' + assignment.getStatus().toString() + '\', ';
output += 'message: \'' + assignment.getMessage() + '\'';
output += ' },\n';
});
output += ' }\n';
}
else {
output += ' tooltipState: \'' + helpers._actual.tooltipState() + '\'\n';
}
output += '});';
return output;
};
/**
* We're splitting status into setup() which alters the state of the system
* and check() which ensures that things are in the right place afterwards.
*/
helpers.setInput = function(typed, cursor) {
helpers._display.inputter.setInput(typed);
if (cursor) {
helpers._display.inputter.setCursor({ start: cursor, end: cursor });
}
helpers._display.focusManager.onInputChange();
test.log('setInput("' + typed + '"' + (cursor == null ? '' : ', ' + cursor) + ')');
};
/**
* Simulate focusing the input field
*/
helpers.focusInput = function() {
helpers._display.inputter.focus();
};
/**
* Simulate pressing TAB in the input field
*/
helpers.pressTab = function() {
helpers.pressKey(9 /*KeyEvent.DOM_VK_TAB*/);
};
/**
* Simulate pressing RETURN in the input field
*/
helpers.pressReturn = function() {
helpers.pressKey(13 /*KeyEvent.DOM_VK_RETURN*/);
};
/**
* Simulate pressing a key by keyCode in the input field
*/
helpers.pressKey = function(keyCode) {
var fakeEvent = {
keyCode: keyCode,
preventDefault: function() { },
timeStamp: new Date().getTime()
};
helpers._display.inputter.onKeyDown(fakeEvent);
helpers._display.inputter.onKeyUp(fakeEvent);
};
/**
* check() is the new status. Similar API except that it doesn't attempt to
* alter the display/requisition at all, and it makes extra checks.
* Available checks:
* input: The text displayed in the input field
* cursor: The position of the start of the cursor
* status: One of "VALID", "ERROR", "INCOMPLETE"
* hints: The hint text, i.e. a concatenation of the directTabText, the
* emptyParameters and the arrowTabText. The text as inserted into the UI
* will include NBSP and Unicode RARR characters, these should be
* represented using normal space and '->' for the arrow
* markup: What state should the error markup be in. e.g. "VVVIIIEEE"
* args: Maps of checks to make against the arguments:
* value: i.e. assignment.value (which ignores defaultValue)
* type: Argument/BlankArgument/MergedArgument/etc i.e. what's assigned
* Care should be taken with this since it's something of an
* implementation detail
* arg: The toString value of the argument
* status: i.e. assignment.getStatus
* message: i.e. assignment.getMessage
* name: For commands - checks assignment.value.name
*/
helpers.check = function(checks) {
if ('input' in checks) {
test.is(helpers._actual.input(), checks.input, 'input');
}
if ('cursor' in checks) {
test.is(helpers._actual.cursor(), checks.cursor, 'cursor');
}
if ('current' in checks) {
test.is(helpers._actual.current(), checks.current, 'current');
}
if ('status' in checks) {
test.is(helpers._actual.status(), checks.status, 'status');
}
if ('markup' in checks) {
test.is(helpers._actual.markup(), checks.markup, 'markup');
}
if ('hints' in checks) {
test.is(helpers._actual.hints(), checks.hints, 'hints');
}
if ('tooltipState' in checks) {
test.is(helpers._actual.tooltipState(), checks.tooltipState, 'tooltipState');
}
if ('outputState' in checks) {
test.is(helpers._actual.outputState(), checks.outputState, 'outputState');
}
if (checks.args != null) {
var requisition = helpers._display.requisition;
Object.keys(checks.args).forEach(function(paramName) {
var check = checks.args[paramName];
var assignment;
if (paramName === 'command') {
assignment = requisition.commandAssignment;
}
else {
assignment = requisition.getAssignment(paramName);
}
if (assignment == null) {
test.ok(false, 'Unknown arg: ' + paramName);
return;
}
if ('value' in check) {
test.is(assignment.value,
check.value,
'arg.' + paramName + '.value');
}
if ('name' in check) {
test.is(assignment.value.name,
check.name,
'arg.' + paramName + '.name');
}
if ('type' in check) {
test.is(assignment.arg.type,
check.type,
'arg.' + paramName + '.type');
}
if ('arg' in check) {
test.is(assignment.arg.toString(),
check.arg,
'arg.' + paramName + '.arg');
}
if ('status' in check) {
test.is(assignment.getStatus().toString(),
check.status,
'arg.' + paramName + '.status');
}
if ('message' in check) {
test.is(assignment.getMessage(),
check.message,
'arg.' + paramName + '.message');
}
});
}
};
/**
* Execute a command:
*
* helpers.exec({
* // Test inputs
* typed: "echo hi", // Optional, uses existing if undefined
*
* // Thing to check
* args: { message: "hi" }, // Check that the args were understood properly
* outputMatch: /^hi$/, // Regex to test against textContent of output
* blankOutput: true, // Special checks when there is no output
* });
*/
helpers.exec = function(tests) {
var requisition = helpers._display.requisition;
var inputter = helpers._display.inputter;
tests = tests || {};
if (tests.typed) {
inputter.setInput(tests.typed);
}
var typed = inputter.getInputState().typed;
var output = requisition.exec({ hidden: true });
test.is(typed, output.typed, 'output.command for: ' + typed);
if (tests.completed !== false) {
test.ok(output.completed, 'output.completed false for: ' + typed);
}
else {
// It is actually an error if we say something is async and it turns
// out not to be? For now we're saying 'no'
// test.ok(!output.completed, 'output.completed true for: ' + typed);
}
if (tests.args != null) {
test.is(Object.keys(tests.args).length, Object.keys(output.args).length,
'arg count for ' + typed);
Object.keys(output.args).forEach(function(arg) {
var expectedArg = tests.args[arg];
var actualArg = output.args[arg];
if (Array.isArray(expectedArg)) {
if (!Array.isArray(actualArg)) {
test.ok(false, 'actual is not an array. ' + typed + '/' + arg);
return;
}
test.is(expectedArg.length, actualArg.length,
'array length: ' + typed + '/' + arg);
for (var i = 0; i < expectedArg.length; i++) {
test.is(expectedArg[i], actualArg[i],
'member: "' + typed + '/' + arg + '/' + i);
}
}
else {
test.is(expectedArg, actualArg, 'typed: "' + typed + '" arg: ' + arg);
}
});
}
if (!options.window.document.createElement) {
test.log('skipping output tests (missing doc.createElement) for ' + typed);
return;
}
var div = options.window.document.createElement('div');
output.toDom(div);
var displayed = div.textContent.trim();
if (tests.outputMatch) {
var doTest = function(match, against) {
if (!match.test(against)) {
test.ok(false, "html output for " + typed + " against " + match.source);
console.log("Actual textContent");
console.log(against);
}
}
if (Array.isArray(tests.outputMatch)) {
tests.outputMatch.forEach(function(match) {
doTest(match, displayed);
});
}
else {
doTest(tests.outputMatch, displayed);
}
}
if (tests.blankOutput != null) {
if (!/^$/.test(displayed)) {
test.ok(false, "html for " + typed + " (textContent sent to info)");
console.log("Actual textContent");
console.log(displayed);
}
}
};

Просмотреть файл

@ -9,8 +9,8 @@ this.EXPORTED_SYMBOLS = [ ];
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/gcli.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
/**
* 'edit' command
@ -40,7 +40,11 @@ gcli.addCommand({
}
],
exec: function(args, context) {
let win = HUDService.currentContext();
win.StyleEditor.openChrome(args.resource.element, args.line);
let target = context.environment.target;
return gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
let styleEditor = toolbox.getCurrentPanel();
styleEditor.selectStyleSheet(args.resource.element, args.line);
return null;
});
}
});

Просмотреть файл

@ -6,179 +6,202 @@
const TEST_URI = "http://example.com/browser/browser/devtools/styleeditor/" +
"test/browser_styleeditor_cmd_edit.html";
function test() {
DeveloperToolbarTest.test(TEST_URI, [ testEditStatus ]);
// Bug 759853
// testEditExec
}
let windowClosed = Promise.defer();
function testEditStatus(browser, tab) {
helpers.setInput('edit');
helpers.check({
input: 'edit',
hints: ' <resource> [line]',
markup: 'VVVV',
status: 'ERROR',
args: {
resource: { status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit i');
helpers.check({
input: 'edit i',
hints: 'nline-css [line]',
markup: 'VVVVVI',
status: 'ERROR',
args: {
resource: { arg: ' i', status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit c');
helpers.check({
input: 'edit c',
hints: 'ss#style2 [line]',
markup: 'VVVVVI',
status: 'ERROR',
args: {
resource: { arg: ' c', status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit http');
helpers.check({
input: 'edit http',
hints: '://example.com/browser/browser/devtools/styleeditor/test/resources_inpage1.css [line]',
markup: 'VVVVVIIII',
status: 'ERROR',
args: {
resource: { arg: ' http', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit page1');
helpers.check({
input: 'edit page1',
hints: ' [line] -> http://example.com/browser/browser/devtools/styleeditor/test/resources_inpage1.css',
markup: 'VVVVVIIIII',
status: 'ERROR',
args: {
resource: { arg: ' page1', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit page2');
helpers.check({
input: 'edit page2',
hints: ' [line] -> http://example.com/browser/browser/devtools/styleeditor/test/resources_inpage2.css',
markup: 'VVVVVIIIII',
status: 'ERROR',
args: {
resource: { arg: ' page2', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit stylez');
helpers.check({
input: 'edit stylez',
hints: ' [line]',
markup: 'VVVVVEEEEEE',
status: 'ERROR',
args: {
resource: { arg: ' stylez', status: 'ERROR', message: 'Can\'t use \'stylez\'.' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit css#style2');
helpers.check({
input: 'edit css#style2',
hints: ' [line]',
markup: 'VVVVVVVVVVVVVVV',
status: 'VALID',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { status: 'VALID' },
}
});
helpers.setInput('edit css#style2 5');
helpers.check({
input: 'edit css#style2 5',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { value: 5, arg: ' 5', status: 'VALID' },
}
});
helpers.setInput('edit css#style2 0');
helpers.check({
input: 'edit css#style2 0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVE',
status: 'ERROR',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { arg: ' 0', status: 'ERROR', message: '0 is smaller than minimum allowed: 1.' },
}
});
helpers.setInput('edit css#style2 -1');
helpers.check({
input: 'edit css#style2 -1',
hints: '',
markup: 'VVVVVVVVVVVVVVVVEE',
status: 'ERROR',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { arg: ' -1', status: 'ERROR', message: '-1 is smaller than minimum allowed: 1.' },
}
});
}
var windowListener = {
onOpenWindow: function(win) {
// Wait for the window to finish loading
let win = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
win.close();
}, false);
win.addEventListener("unload", function onUnload() {
win.removeEventListener("unload", onUnload, false);
Services.wm.removeListener(windowListener);
finish();
}, false);
},
onCloseWindow: function(win) { },
onWindowTitleChange: function(win, title) { }
};
function testEditExec(browser, tab) {
Services.wm.addListener(windowListener);
var style2 = browser.contentDocument.getElementById("style2");
DeveloperToolbarTest.exec({
typed: "edit css#style2",
args: {
resource: function(resource) {
return resource.element.ownerNode == style2;
helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.audit(options, [
{
setup: "edit",
check: {
input: 'edit',
hints: ' <resource> [line]',
markup: 'VVVV',
status: 'ERROR',
args: {
resource: { status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
},
},
line: 1
},
completed: true,
blankOutput: true,
});
{
setup: "edit i",
check: {
input: 'edit i',
hints: 'nline-css [line]',
markup: 'VVVVVI',
status: 'ERROR',
args: {
resource: { arg: ' i', status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit c",
check: {
input: 'edit c',
hints: 'ss#style2 [line]',
markup: 'VVVVVI',
status: 'ERROR',
args: {
resource: { arg: ' c', status: 'INCOMPLETE' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit http",
check: {
input: 'edit http',
hints: '://example.com/browser/browser/devtools/styleeditor/test/resources_inpage1.css [line]',
markup: 'VVVVVIIII',
status: 'ERROR',
args: {
resource: { arg: ' http', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit page1",
check: {
input: 'edit page1',
hints: ' [line] -> http://example.com/browser/browser/devtools/styleeditor/test/resources_inpage1.css',
markup: 'VVVVVIIIII',
status: 'ERROR',
args: {
resource: { arg: ' page1', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit page2",
check: {
input: 'edit page2',
hints: ' [line] -> http://example.com/browser/browser/devtools/styleeditor/test/resources_inpage2.css',
markup: 'VVVVVIIIII',
status: 'ERROR',
args: {
resource: { arg: ' page2', status: 'INCOMPLETE', message: '' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit stylez",
check: {
input: 'edit stylez',
hints: ' [line]',
markup: 'VVVVVEEEEEE',
status: 'ERROR',
args: {
resource: { arg: ' stylez', status: 'ERROR', message: 'Can\'t use \'stylez\'.' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit css#style2",
check: {
input: 'edit css#style2',
hints: ' [line]',
markup: 'VVVVVVVVVVVVVVV',
status: 'VALID',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { status: 'VALID' },
}
},
},
{
setup: "edit css#style2 5",
check: {
input: 'edit css#style2 5',
hints: '',
markup: 'VVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { value: 5, arg: ' 5', status: 'VALID' },
}
},
},
{
setup: "edit css#style2 0",
check: {
input: 'edit css#style2 0',
hints: '',
markup: 'VVVVVVVVVVVVVVVVE',
status: 'ERROR',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { arg: ' 0', status: 'ERROR', message: '0 is smaller than minimum allowed: 1.' },
}
},
},
{
setup: "edit css#style2 -1",
check: {
input: 'edit css#style2 -1',
hints: '',
markup: 'VVVVVVVVVVVVVVVVEE',
status: 'ERROR',
args: {
resource: { arg: ' css#style2', status: 'VALID', message: '' },
line: { arg: ' -1', status: 'ERROR', message: '-1 is smaller than minimum allowed: 1.' },
}
},
},
{
// Bug 759853
skipIf: true,
name: "edit exec",
setup: function() {
var windowListener = {
onOpenWindow: function(win) {
// Wait for the window to finish loading
let win = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
win.close();
}, false);
win.addEventListener("unload", function onUnload() {
win.removeEventListener("unload", onUnload, false);
Services.wm.removeListener(windowListener);
windowClosed.resolve();
}, false);
},
onCloseWindow: function(win) { },
onWindowTitleChange: function(win, title) { }
};
Services.wm.addListener(windowListener);
helpers.setInput(options, "edit css#style2");
},
check: {
input: "edit css#style2",
args: {
resource: {
value: function(resource) {
let style2 = options.window.document.getElementById("style2");
return resource.element.ownerNode == style2;
}
},
line: { value: 1 },
},
},
exec: {
output: "",
},
post: function() {
return windowClosed.promise;
}
},
]);
}).then(finish);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -92,9 +92,9 @@ typesNumberMax=%1$S is greater than maximum allowed: %2$S.
# message is displayed.
typesNumberMin=%1$S is smaller than minimum allowed: %2$S.
# LOCALIZATION NOTE (typesNumberNotInt): When the command line is passed a
# LOCALIZATION NOTE (typesNumberNotInt2): When the command line is passed a
# number, but the number has a decimal part and floats are not allowed.
typesNumberNotInt='%S' must be an integer.
typesNumberNotInt2=Can't convert "%S" to an integer.
# LOCALIZATION NOTE (typesSelectionNomatch): When the command line is passed
# an option with a limited number of correct values, but the passed value is

Просмотреть файл

@ -1006,3 +1006,27 @@ callLogChromeEvalNeedsObject=The JavaScript source must evaluate to an object wh
# LOCALIZATION NOTE (scratchpadOpenTooltip) A string displayed as the
# tooltip of button in devtools toolbox which opens Scratchpad.
scratchpadOpenTooltip=Scratchpad
# LOCALIZATION NOTE (paintflashingDesc) A very short string used to describe the
# function of the "paintflashing" command
paintflashingDesc=Highlight painted area
# LOCALIZATION NOTE (paintflashingOnDesc) A very short string used to describe the
# function of the "paintflashing on" command.
paintflashingOnDesc=Turn on paint flashing
# LOCALIZATION NOTE (paintflashingOffDesc) A very short string used to describe the
# function of the "paintflashing off" command.
paintflashingOffDesc=Turn off paint flashing
# LOCALIZATION NOTE (paintflashingChrome) A very short string used to describe the
# function of the "paintflashing on/off chrome" command.
paintflashingChromeDesc=chrome frames
# LOCALIZATION NOTE (paintflashingManual) A longer description describing the
# set of commands that control paint flashing.
paintflashingManual=Draw repainted areas in different colors
# LOCALIZATION NOTE (paintflashingTooltip) A string displayed as the
# tooltip of button in devtools toolbox which toggles paint flashing.
paintflashingTooltip=Highlight painted area

Просмотреть файл

@ -105,6 +105,7 @@ var BrowserUI = {
}
FlyoutPanelsUI.init();
PageThumbs.init();
SettingsCharm.init();
// show the right toolbars, awesomescreen, etc for the os viewstate
BrowserUI._adjustDOMforViewState();
@ -155,11 +156,6 @@ var BrowserUI = {
Util.dumpLn("Exception in delay load module:", ex.message);
}
try {
SettingsCharm.init();
} catch (ex) {
}
try {
// XXX This is currently failing
CapturePickerUI.init();
@ -1734,8 +1730,13 @@ var SettingsCharm = {
* and an "onselected" property (function to be called when the user chooses this entry)
*/
addEntry: function addEntry(aEntry) {
let id = MetroUtils.addSettingsPanelEntry(aEntry.label);
this._entries.set(id, aEntry);
try {
let id = MetroUtils.addSettingsPanelEntry(aEntry.label);
this._entries.set(id, aEntry);
} catch (e) {
// addSettingsPanelEntry does not work on non-Metro platforms
Cu.reportError(e);
}
},
init: function SettingsCharm_init() {

Просмотреть файл

@ -42,10 +42,10 @@ XPCSHELL_RESOURCES = \
$(NULL)
libs:: $(BROWSER_TESTS)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/$(relativesrcdir)
libs:: $(BROWSER_TEST_RESOURCES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/res
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/metro/$(relativesrcdir)/res
libs:: $(XPCSHELL_RESOURCES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/

Просмотреть файл

@ -436,14 +436,15 @@ pref("app.update.showInstalledUI", false);
pref("app.update.incompatible.mode", 0);
pref("app.update.download.backgroundInterval", 0);
// %APP% resolves to metrofirefox, which won't work until bug 845983 is fixed
#ifdef MOZ_OFFICIAL_BRANDING
pref("app.update.interval", 86400);
pref("app.update.url.manual", "http://www.mozilla.com/%LOCALE%/m/");
pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/mobile/releases/");
pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/update/");
pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/releases/");
#else
pref("app.update.interval", 28800);
pref("app.update.url.manual", "http://www.mozilla.com/%LOCALE%/mobile/");
pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/mobile/");
pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/");
pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/");
#endif
#endif

Двоичные данные
browser/themes/linux/devtools/command-paintflashing.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 961 B

Просмотреть файл

@ -71,6 +71,20 @@
background-color: hsla(206,37%,4%,.4);
}
#command-button-paintflashing {
list-style-image: url("chrome://browser/skin/devtools/command-paintflashing.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
#command-button-paintflashing:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
#command-button-paintflashing:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
}
#command-button-paintflashing[checked=true] {
-moz-image-region: rect(0px, 64px, 16px, 48px);
}
#command-button-responsive {
list-style-image: url("chrome://browser/skin/devtools/command-responsivemode.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);

Просмотреть файл

@ -114,6 +114,7 @@ browser.jar:
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)

Двоичные данные
browser/themes/osx/devtools/command-paintflashing.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 961 B

Просмотреть файл

@ -59,6 +59,20 @@
background-color: hsla(206,37%,4%,.4);
}
#command-button-paintflashing {
list-style-image: url("chrome://browser/skin/devtools/command-paintflashing.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
#command-button-paintflashing:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
#command-button-paintflashing:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
}
#command-button-paintflashing[checked=true] {
-moz-image-region: rect(0px, 64px, 16px, 48px);
}
#command-button-responsive {
list-style-image: url("chrome://browser/skin/devtools/command-responsivemode.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);

Просмотреть файл

@ -194,6 +194,7 @@ browser.jar:
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)

Двоичные данные
browser/themes/windows/devtools/command-paintflashing.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 961 B

Просмотреть файл

@ -74,6 +74,20 @@
background-color: hsla(206,37%,4%,.4);
}
#command-button-paintflashing {
list-style-image: url("chrome://browser/skin/devtools/command-paintflashing.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
#command-button-paintflashing:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px);
}
#command-button-paintflashing:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
}
#command-button-paintflashing[checked=true] {
-moz-image-region: rect(0px, 64px, 16px, 48px);
}
#command-button-responsive {
list-style-image: url("chrome://browser/skin/devtools/command-responsivemode.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);

Просмотреть файл

@ -144,6 +144,7 @@ browser.jar:
skin/classic/browser/devtools/goto-mdn.png (devtools/goto-mdn.png)
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/commandline.css (devtools/commandline.css)
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
skin/classic/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
skin/classic/browser/devtools/command-tilt.png (devtools/command-tilt.png)
@ -370,6 +371,7 @@ browser.jar:
skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
skin/classic/aero/browser/devtools/arrows.png (devtools/arrows.png)
skin/classic/aero/browser/devtools/commandline.png (devtools/commandline.png)
skin/classic/aero/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
skin/classic/aero/browser/devtools/command-scratchpad.png (devtools/command-scratchpad.png)
skin/classic/aero/browser/devtools/command-tilt.png (devtools/command-tilt.png)

Просмотреть файл

@ -3210,6 +3210,35 @@ nsDOMWindowUtils::IsNodeDisabledForEvents(nsIDOMNode* aNode, bool* aRetVal)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetPaintFlashing(bool aPaintFlashing)
{
nsPresContext* presContext = GetPresContext();
if (presContext) {
presContext->RefreshDriver()->SetPaintFlashing(aPaintFlashing);
// Clear paint flashing colors
nsIPresShell* presShell = GetPresShell();
if (!aPaintFlashing && presShell) {
nsIFrame* rootFrame = presShell->GetRootFrame();
if (rootFrame) {
rootFrame->InvalidateFrameSubtree();
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPaintFlashing(bool* aRetVal)
{
*aRetVal = false;
nsPresContext* presContext = GetPresContext();
if (presContext) {
*aRetVal = presContext->RefreshDriver()->GetPaintFlashing();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::DispatchEventToChromeOnly(nsIDOMEventTarget* aTarget,
nsIDOMEvent* aEvent,

Просмотреть файл

@ -1349,4 +1349,9 @@ interface nsIDOMWindowUtils : nsISupports {
* attribute or -moz-user-input: none/disabled.
*/
boolean isNodeDisabledForEvents(in nsIDOMNode aNode);
/**
* Setting paintFlashing to true will flash newly painted area.
*/
attribute boolean paintFlashing;
};

Просмотреть файл

@ -759,22 +759,11 @@ FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager)
void
FrameLayerBuilder::FlashPaint(gfxContext *aContext)
{
static bool sPaintFlashingEnabled;
static bool sPaintFlashingPrefCached = false;
if (!sPaintFlashingPrefCached) {
sPaintFlashingPrefCached = true;
mozilla::Preferences::AddBoolVarCache(&sPaintFlashingEnabled,
"nglayout.debug.paint_flashing");
}
if (sPaintFlashingEnabled) {
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aContext->SetColor(gfxRGBA(r, g, b, 0.2));
aContext->Paint();
}
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aContext->SetColor(gfxRGBA(r, g, b, 0.4));
aContext->Paint();
}
FrameLayerBuilder::DisplayItemData*
@ -3361,7 +3350,10 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
aContext->Restore();
}
FlashPaint(aContext);
if (presContext->RefreshDriver()->GetPaintFlashing()) {
FlashPaint(aContext);
}
if (!aRegionToInvalidate.IsEmpty()) {
aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
}

Просмотреть файл

@ -528,6 +528,8 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext)
mMostRecentRefreshEpochTime = JS_Now();
mMostRecentRefresh = TimeStamp::Now();
mPaintFlashing = Preferences::GetBool("nglayout.debug.paint_flashing");
mRequests.Init();
}

Просмотреть файл

@ -229,6 +229,17 @@ public:
*/
static int32_t DefaultInterval();
/**
* Enable/disable paint flashing.
*/
void SetPaintFlashing(bool aPaintFlashing) {
mPaintFlashing = aPaintFlashing;
}
bool GetPaintFlashing() {
return mPaintFlashing;
}
private:
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
@ -265,6 +276,7 @@ private:
bool mTestControllingRefreshes;
bool mViewManagerFlushIsPending;
bool mRequestedHighPrecision;
bool mPaintFlashing;
int64_t mMostRecentRefreshEpochTime;
mozilla::TimeStamp mMostRecentRefresh;

Просмотреть файл

@ -51,6 +51,7 @@ MOCHITEST_CHROME_FILES = \
test_passpointerevents.html \
passpointerevents_window.html \
test_bug812817.xul \
test_bug847890_paintFlashing.html \
$(NULL)
ifdef MOZ_DEBUG

Просмотреть файл

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Tests for paint flashing</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
function startTest() {
waitForAllPaintsFlushed(function () {
var before = snapshotWindow(window, false);
SpecialPowers.getDOMWindowUtils(window).paintFlashing = true;
document.body.innerHTML = "bar";
waitForAllPaintsFlushed(function () {
document.body.innerHTML = "foo";
waitForAllPaintsFlushed(function () {
var after = snapshotWindow(window, false);
ok(compareSnapshots(before, after, false)[0], "windows are different");
SpecialPowers.getDOMWindowUtils(window).paintFlashing = false;
SimpleTest.finish();
});
});
});
}
</script>
</head>
<body onload="startTest()">foo</body>
</html>

Просмотреть файл

@ -161,7 +161,7 @@ def checkout_tag(src, directory, version):
"""
if version is None:
tag = 'HEAD'
tag = 'master'
else:
tag = version_tag(directory, version)
checkout(src, tag)
@ -227,7 +227,11 @@ def main(args=sys.argv[1:]):
parser.add_option('-o', '--output', dest='output',
help="specify the output file; otherwise will be in the current directory with a name based on the hash")
parser.add_option('--develop', dest='develop',
help="use development (HEAD) version of packages")
action='store_true', default=False,
help="use development (master) version of packages")
parser.add_option('--no-check', dest='check',
action='store_false', default=True,
help="Do not check current repository state")
parser.add_option('--packages', dest='output_packages',
default=False, action='store_true',
help="generate packages.txt and exit")
@ -268,12 +272,12 @@ def main(args=sys.argv[1:]):
# ensure there are no outstanding changes to m-c
process = subprocess.Popen(['hg', 'diff'], cwd=here, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if stdout.strip():
if stdout.strip() and options.check:
error("Outstanding changes in %s; aborting" % hg_root)
# ensure that there are no untracked files in testing/mozbase
untracked = untracked_files(hg_root)
if untracked:
if untracked and options.check:
error("Untracked files in %s:\n %s\naborting" % (hg_root, '\n'.join([' %s' % i for i in untracked])))
tempdir = tempfile.mkdtemp()
@ -299,7 +303,7 @@ def main(args=sys.argv[1:]):
if not version:
if options.develop:
# use HEAD of package; keep version=None
# use master of package; keep version=None
continue
# choose maximum version from setup.py
@ -338,7 +342,7 @@ def main(args=sys.argv[1:]):
sys.modules.pop('setuptools')
if setuptools:
sys.modules['setuptools'] = setuptools
checkout(src, 'HEAD')
checkout(src, 'master')
check_consistency(*current_package_info.values())
# copy mozbase directories to m-c
@ -355,7 +359,9 @@ def main(args=sys.argv[1:]):
generate_packages_txt()
# generate the diff and write to output file
call(['hg', 'addremove'], cwd=hg_root)
command = ['hg', 'addremove']
# TODO: don't add untracked files via `hg addremove --exclude...`
call(command, cwd=hg_root)
process = subprocess.Popen(['hg', 'diff'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,