Bug 683506 - GCLI needs an 'inspect' command; r=msucan,l10n
authorJoe Walker <jwalker@mozilla.com>
Wed, 26 Oct 2011 11:03:12 -0300
changeset 79286 332d8f5f588622f83d4152d9928d43cbc2b53064
parent 79285 bfb669703e33953aaad2b3a2ed427a1585e20ce5
child 79287 ca0e85e9fe899c8bea6470056b6b0538f2a83a38
push id21383
push usermleibovic@mozilla.com
push dateThu, 27 Oct 2011 18:30:56 +0000
treeherdermozilla-central@322354df233d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmsucan, l10n
bugs683506
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 683506 - GCLI needs an 'inspect' command; r=msucan,l10n
browser/devtools/webconsole/GcliCommands.jsm
browser/devtools/webconsole/gcli.jsm
browser/devtools/webconsole/test/browser/Makefile.in
browser/devtools/webconsole/test/browser/browser_gcli_inspect.html
browser/devtools/webconsole/test/browser/browser_gcli_inspect.js
browser/devtools/webconsole/test/browser/browser_gcli_web.js
browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
--- a/browser/devtools/webconsole/GcliCommands.jsm
+++ b/browser/devtools/webconsole/GcliCommands.jsm
@@ -112,8 +112,30 @@ gcli.addCommand({
   name: "console clear",
   description: gcli.lookup("consoleclearDesc"),
   exec: function(args, context) {
     let hud = HUDService.getHudReferenceById(context.environment.hudId);
     hud.gcliterm.clearOutput();
   }
 });
 
+
+/**
+ * 'inspect' command
+ */
+gcli.addCommand({
+  name: "inspect",
+  description: gcli.lookup("inspectDesc"),
+  manual: gcli.lookup("inspectManual"),
+  params: [
+    {
+      name: "node",
+      type: "node",
+      description: gcli.lookup("inspectNodeDesc"),
+      manual: gcli.lookup("inspectNodeManual")
+    }
+  ],
+  exec: function Command_inspect(args, context) {
+    let hud = HUDService.getHudReferenceById(context.environment.hudId);
+    let InspectorUI = hud.gcliterm.document.defaultView.InspectorUI;
+    InspectorUI.openInspectorUI(args.node);
+  }
+});
--- a/browser/devtools/webconsole/gcli.jsm
+++ b/browser/devtools/webconsole/gcli.jsm
@@ -3473,19 +3473,20 @@ exports.JavascriptType = JavascriptType;
 
 });
 /*
  * 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('gcli/types/node', ['require', 'exports', 'module' , 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
-
-
+define('gcli/types/node', ['require', 'exports', 'module' , 'gcli/host', 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
+
+
+var host = require('gcli/host');
 var l10n = require('gcli/l10n');
 var types = require('gcli/types');
 var Type = require('gcli/types').Type;
 var Status = require('gcli/types').Status;
 var Conversion = require('gcli/types').Conversion;
 
 
 /**
@@ -3557,47 +3558,57 @@ NodeType.prototype.parse = function(arg)
     return new Conversion(null, arg, Status.INCOMPLETE,
         l10n.lookup('nodeParseNone'));
   }
 
   if (nodes.length === 1) {
     var node = nodes.item(0);
     node.__gcliQuery = arg.text;
 
-    flashNode(node, 'green');
+    host.flashNode(node, 'green');
 
     return new Conversion(node, arg, Status.VALID, '');
   }
 
   Array.prototype.forEach.call(nodes, function(n) {
-    flashNode(n, 'red');
+    host.flashNode(n, 'red');
   });
 
   return new Conversion(null, arg, Status.ERROR,
           l10n.lookupFormat('nodeParseMultiple', [ nodes.length ]));
 };
 
 NodeType.prototype.name = 'node';
 
 
+});
+/*
+ * 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('gcli/host', ['require', 'exports', 'module' ], function(require, exports, module) {
+
+
 /**
  * Helper to turn a node background it's complementary color for 1 second.
  * There is likely a better way to do this, but this will do for now.
  */
-function flashNode(node, color) {
+exports.flashNode = function(node, color) {
   if (!node.__gcliHighlighting) {
     node.__gcliHighlighting = true;
     var original = node.style.background;
     node.style.background = color;
     setTimeout(function() {
       node.style.background = original;
       delete node.__gcliHighlighting;
     }, 1000);
   }
-}
+};
 
 
 });
 /*
  * Copyright 2009-2011 Mozilla Foundation and contributors
  * Licensed under the New BSD license. See LICENSE.txt or:
  * http://opensource.org/licenses/BSD-3-Clause
  */
--- a/browser/devtools/webconsole/test/browser/Makefile.in
+++ b/browser/devtools/webconsole/test/browser/Makefile.in
@@ -140,18 +140,19 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_bug_585991_autocomplete_keys.js \
 	browser_webconsole_bug_663443_panel_title.js \
 	browser_webconsole_bug_660806_history_nav.js \
 	browser_webconsole_bug_651501_document_body_autocomplete.js \
 	browser_webconsole_bug_653531_highlighter_console_helper.js \
 	browser_webconsole_bug_659907_console_dir.js \
 	browser_webconsole_bug_678816.js \
 	browser_webconsole_bug_664131_console_group.js \
+	browser_gcli_inspect.js \
+	browser_gcli_integrate.js \
 	browser_gcli_require.js \
-	browser_gcli_integrate.js \
 	browser_gcli_web.js \
 	head.js \
 	$(NULL)
 
 _BROWSER_TEST_PAGES = \
 	test-console.html \
 	test-network.html \
 	test-network-request.html \
@@ -213,15 +214,16 @@ include $(topsrcdir)/config/rules.mk
 	test-bug-621644-jsterm-dollar.html \
 	test-bug-632347-iterators-generators.html \
 	test-bug-585956-console-trace.html \
 	test-bug-644419-log-limits.html \
 	test-bug-632275-getters.html \
 	test-bug-646025-console-file-location.html \
 	test-bug-678816-content.js \
 	test-file-location.js \
+	browser_gcli_inspect.html \
 	$(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 
 libs:: $(_BROWSER_TEST_PAGES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser/browser_gcli_inspect.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <title>GCLI inspect command test</title>
+</head>
+<body>
+
+  <!-- This is a list of 0 h1 elements -->
+
+  <!-- This is a list of 1 div elements -->
+  <div>Hello, I'm a div</div>
+
+  <!-- This is a list of 2 span elements -->
+  <span>Hello, I'm a span</span>
+  <span>And me</span>
+
+  <!-- This is a collection of various things that match only once -->
+  <p class="someclass">.someclass</p>
+  <p id="someid">#someid</p>
+  <button disabled>button[disabled]</button>
+  <p><strong>p&gt;strong</strong></p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser/browser_gcli_inspect.js
@@ -0,0 +1,93 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// For more information on GCLI see:
+// - https://github.com/mozilla/gcli/blob/master/docs/index.md
+// - https://wiki.mozilla.org/DevTools/Features/GCLI
+
+// Tests that the inspect command works as it should
+
+Components.utils.import("resource:///modules/gcli.jsm");
+
+registerCleanupFunction(function() {
+  gcliterm = undefined;
+  requisition = undefined;
+
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
+function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", true);
+  addTab("http://example.com/browser/browser/devtools/webconsole/test/browser/browser_gcli_inspect.html");
+  browser.addEventListener("DOMContentLoaded", onLoad, false);
+}
+
+let gcliterm;
+let requisition;
+
+function onLoad() {
+  browser.removeEventListener("DOMContentLoaded", onLoad, false);
+
+  try {
+    openConsole();
+
+    let hud = HUDService.getHudByWindow(content);
+    gcliterm = hud.gcliterm;
+    requisition = gcliterm.opts.requisition;
+
+    testSetup();
+    testCreateCommands();
+  }
+  catch (ex) {
+    ok(false, "Caught exception: " + ex)
+    gcli._internal.console.error("Test Failure", ex);
+  }
+  finally {
+    closeConsole();
+    finishTest();
+  }
+}
+
+function testSetup() {
+  ok(gcliterm, "We have a GCLI term");
+  ok(requisition, "We have a Requisition");
+}
+
+function testCreateCommands() {
+  type("inspec");
+  is(gcliterm.completeNode.textContent, " inspect", "Completion for \"inspec\"");
+  is(requisition.getStatus().toString(), "ERROR", "inspec is ERROR");
+
+  type("inspect");
+  is(requisition.getStatus().toString(), "ERROR", "inspect is ERROR");
+
+  type("inspect h1");
+  is(requisition.getStatus().toString(), "ERROR", "inspect h1 is ERROR");
+
+  type("inspect span");
+  is(requisition.getStatus().toString(), "ERROR", "inspect span is ERROR");
+
+  type("inspect div");
+  is(requisition.getStatus().toString(), "VALID", "inspect div is VALID");
+
+  type("inspect .someclass");
+  is(requisition.getStatus().toString(), "VALID", "inspect .someclass is VALID");
+
+  type("inspect #someid");
+  is(requisition.getStatus().toString(), "VALID", "inspect #someid is VALID");
+
+  type("inspect button[disabled]");
+  is(requisition.getStatus().toString(), "VALID", "inspect button[disabled] is VALID");
+
+  type("inspect p>strong");
+  is(requisition.getStatus().toString(), "VALID", "inspect p>strong is VALID");
+
+  type("inspect :root");
+  is(requisition.getStatus().toString(), "VALID", "inspect :root is VALID");
+}
+
+function type(command) {
+  gcliterm.inputNode.value = command.slice(0, -1);
+  gcliterm.inputNode.focus();
+  EventUtils.synthesizeKey(command.slice(-1), {});
+}
--- a/browser/devtools/webconsole/test/browser/browser_gcli_web.js
+++ b/browser/devtools/webconsole/test/browser/browser_gcli_web.js
@@ -49,28 +49,27 @@ var define = obj.gcli._internal.define;
 var console = obj.gcli._internal.console;
 var Node = Components.interfaces.nsIDOMNode;
 /*
  * Copyright 2009-2011 Mozilla Foundation and contributors
  * Licensed under the New BSD license. See LICENSE.txt or:
  * http://opensource.org/licenses/BSD-3-Clause
  */
 
-define('gclitest/index', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
+define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
 
   // We need to make sure GCLI is initialized before we begin testing it
   require('gcli/index');
 
   var examiner = require('test/examiner');
 
   examiner.addSuite('gclitest/testTokenize', require('gclitest/testTokenize'));
   examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit'));
   examiner.addSuite('gclitest/testCli', require('gclitest/testCli'));
   examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory'));
-
   examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire'));
 
   examiner.run();
 
 });
 /*
  * Copyright 2009-2011 Mozilla Foundation and contributors
  * Licensed under the New BSD license. See LICENSE.txt or:
@@ -1368,28 +1367,28 @@ define('gclitest/requirable', ['require'
 
   var status = 'initial';
   exports.setStatus = function(aStatus) { status = aStatus; };
   exports.getStatus = function() { return status; };
 
 });
 
 function undefine() {
-  delete define.modules['gclitest/index'];
+  delete define.modules['gclitest/suite'];
   delete define.modules['test/examiner'];
   delete define.modules['gclitest/testTokenize'];
   delete define.modules['test/assert'];
   delete define.modules['gclitest/testSplit'];
   delete define.modules['gclitest/commands'];
   delete define.modules['gclitest/testCli'];
   delete define.modules['gclitest/testHistory'];
   delete define.modules['gclitest/testRequire'];
   delete define.modules['gclitest/requirable'];
 
-  delete define.globalDomain.modules['gclitest/index'];
+  delete define.globalDomain.modules['gclitest/suite'];
   delete define.globalDomain.modules['test/examiner'];
   delete define.globalDomain.modules['gclitest/testTokenize'];
   delete define.globalDomain.modules['test/assert'];
   delete define.globalDomain.modules['gclitest/testSplit'];
   delete define.globalDomain.modules['gclitest/commands'];
   delete define.globalDomain.modules['gclitest/testCli'];
   delete define.globalDomain.modules['gclitest/testHistory'];
   delete define.globalDomain.modules['gclitest/testRequire'];
--- a/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
@@ -30,8 +30,30 @@ consoleDesc=Commands to control the cons
 
 # LOCALIZATION NOTE (consoleManual) A longer description describing the
 # set of commands that control the console.
 consoleManual=Filter, clear and close the web console
 
 # LOCALIZATION NOTE (consoleclearDesc) A very short string used to describe the
 # function of the 'console clear' command.
 consoleclearDesc=Clear the console
+
+# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
+# command. See inspectManual for a fuller description of what it does. This
+# string is designed to be shown in a menu alongside the command name, which
+# is why it should be as short as possible.
+inspectDesc=Inspect a node
+
+# LOCALIZATION NOTE (inspectManual) A fuller description of the 'inspect'
+# command, displayed when the user asks for help on what it does.
+inspectManual=Investigate the dimensions and properties of an element using \
+a CSS selector to open the DOM highlighter
+
+# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
+# 'node' parameter to the 'inspect' command, which is displayed in a dialog
+# when the user is using this command.
+inspectNodeDesc=CSS selector
+
+# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
+# parameter to the 'inspect' command, displayed when the user asks for help
+# on what it does.
+inspectNodeManual=A CSS selector for use with Document.querySelector which \
+identifies a single element