changeset 100:c486d35fad27

added more mocks; black-box now talks to a really simple fake bugzilla 'server'.
author Atul Varma <avarma@mozilla.com>
date Tue, 27 Apr 2010 23:06:29 -0700
parents 544d339d2b4c
children 106a0018e601
files js/black-box.js js/modules/mocks.js
diffstat 2 files changed, 194 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/js/black-box.js	Tue Apr 27 09:59:15 2010 -0700
+++ b/js/black-box.js	Tue Apr 27 23:06:29 2010 -0700
@@ -1,5 +1,29 @@
+function getXPathForElement(el, xml) {
+  var xpath = "";
+  var pos, tempitem2;
+  
+  while (el !== xml.documentElement) {    
+    pos = 0;
+    tempitem2 = el;
+    while (tempitem2) {
+      if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) {
+        // If it is ELEMENT_NODE of the same name
+        pos += 1;
+      }
+      tempitem2 = tempitem2.previousSibling;
+    }
+    
+    xpath = el.nodeName + "[" + pos + "]" + "/" + xpath;
+
+    el = el.parentNode;
+  }
+  xpath = "/" + xml.documentElement.nodeName + "/" + xpath;
+  xpath = xpath.replace(/\/$/, '');
+  return xpath;
+}
+
 function onDashboardLoaded(dashboard, options) {
-  var require = Require.build();
+  var require = Require.build(Require.modules, {window: window});
 
   // Needed for Firebug, which won't log iframe errors to the console.
   $(dashboard).error(
@@ -7,11 +31,64 @@
       console.warn("An error occurred in the dashboard iframe.");
     });
 
+  function DOMElementToCSSSelector(element) {
+    if (element.id)
+      return "#" + element.id;
+
+    var document = element.ownerDocument;
+
+    function isUnique(selector) {
+      return (document.querySelectorAll(selector).length == 1);
+    }
+
+    var parent = element.parentNode;
+    while (parent) {
+      if (parent.id)
+        break;
+      parent = parent.parentNode;
+    }
+
+    if (parent && parent.id) {
+      var selector = "#" + parent.id;
+
+      var list = element.classList;
+      for (var i = 0; i < list.length; i++) {
+        selector += " ." + list[i];
+        if (isUnique(selector))
+          return selector;
+      }
+    }
+    return null;
+  }
+
+  dashboard.addEventListener(
+    "mousedown",
+    function(event) {
+      var document = event.target.ownerDocument;
+      var xpath = getXPathForElement(event.target, document);
+      var result = document.evaluate(xpath, document, null,
+                                     XPathResult.ANY_TYPE, null);
+      console.log("mousedown", event.target,
+                  DOMElementToCSSSelector(event.target),
+                  xpath,
+                  result.iterateNext());
+    },
+    true
+  );
+
   var moduleExports = {};
   var dbrequire = dashboard.Require.build(dashboard.Require.modules,
                                           moduleExports);
-  options.cache = require("mocks/cache").create();
-  options.Bugzilla = require("mocks/bugzilla").create(options.Bugzilla);
+
+  function delegate(method, args) {
+    //console.log(method, args);
+  }
+
+  var ajaxImpl = require("mocks/bugzilla/trivial").makeAjaxImpl();
+  options.cache = require("mocks/cache").create(delegate);
+  options.Bugzilla = require("mocks/bugzilla").create(options.Bugzilla,
+                                                      ajaxImpl,
+                                                      delegate);
   dbrequire("date-utils").now = function() {
     return new Date("Tue Apr 27 2010 09:00:00 GMT");
   };
--- a/js/modules/mocks.js	Tue Apr 27 09:59:15 2010 -0700
+++ b/js/modules/mocks.js	Tue Apr 27 23:06:29 2010 -0700
@@ -1,39 +1,142 @@
 Require.modules["mocks/cache"] = function(exports, require) {
   function copy(obj) {
-    return JSON.parse(JSON.stringify(obj));
+    if (typeof(obj) == "function")
+      throw new Error("can't store functions");
+    if (typeof(obj) == "object")
+      return JSON.parse(JSON.stringify(obj));
+    return obj;
   }
 
-  function MockCache() {
+  function MockCache(delegate) {
+    this.delegate = delegate;
     this.cache = {};
   };
 
   MockCache.prototype = {
     get: function get(key) {
-      console.log("cache get", key);
+      this.delegate("get", [key]);
       if (key in this.cache)
         return copy(this.cache[key]);
       return null;
     },
     set: function set(key, value) {
-      console.log("cache set", key);
+      this.delegate("set", [key, value]);
       this.cache[key] = copy(value);
     },
-    clear: function clear(key, value) {
+    clear: function clear() {
+      this.delegate("clear", []);
       this.cache = {};
     }
   };
 
-  exports.create = function create() {
-    return new MockCache();
+  exports.create = function create(delegate) {
+    return new MockCache(delegate);
+  };
+};
+
+Require.modules["mocks/bugzilla/trivial"] = function(exports, require) {
+  var bug = {
+    'summary': 'Application destroys computer on startup',
+    'last_change_time': '2010-04-13T18:02:00Z',
+    'status': 'NEW',
+    'priority': 'P1',
+    'severity': 'blocker',
+    'id': '558680'
+  };
+
+  var user = {
+    'email': 'john@doe.com',
+    'real_name': 'John Doe',
+    'name': 'john@doe.com'
+    };
+
+  var config = {
+    product: {
+      foo: {
+        component: {
+          caching: {},
+          passwords: {}
+        }
+      },
+      bar: {
+        component: {
+          "help system": {},
+          "curmudgeonry": {}
+        }
+      }
+    }
+  };
+
+  exports.makeAjaxImpl = function makeAjaxImpl(delegate, setTimeout) {
+    return function ajaxImpl(options) {
+      var authenticated = false;
+      if (options.data && options.data.username) {
+        if (!(options.data.username == 'john@doe.com' &&
+              options.data.password == 'test'))
+          return {error: true, message: "wrong password, yo!"};
+        authenticated = true;
+      }
+      switch (options.url) {
+      case "/bug":
+        if (!('resolution' in options.data))
+          return {bugs: [bug]};
+        return {bugs: []};
+      case "/configuration":
+        return config;
+      case "/user":
+        if (!authenticated)
+          return {error: true, message: "needs login, yo!"};
+        if (user.email.indexOf(options.data.match) != -1 ||
+            user.real_name.indexOf(options.data.match) != -1)
+          return {users: [user]};
+        return {users: []};
+      default:
+        throw new Error("unexpected url: " + options.url);
+      }
+    };
   };
 };
 
 Require.modules["mocks/bugzilla"] = function(exports, require) {
-  exports.create = function create(Bugzilla) {
+  const DEFAULT_RESPONSE_TIME = 500;
+
+  function response(delegate, obj, time) {
+    if (time === undefined)
+      time = DEFAULT_RESPONSE_TIME;
+
+    function xhrDelegate(method, args) {
+      delegate("xhr." + method, args);
+    }
+
+    var req = require("mocks/xhr").create(xhrDelegate);
+
+    require("window").setTimeout(
+      function() {
+        req.responseText = JSON.stringify(obj);
+        req.status = 200;
+        req.statusText = "OK";
+        req.mockTriggerEvent({type: "load", target: req});
+      },
+      time
+    );
+    return req;
+  }
+
+  exports.create = function create(Bugzilla, ajaxImpl, delegate) {
     function MockBugzilla() {
       this.ajax = function ajax(options) {
-        console.log(options);
-        throw new Error("MockBugzilla.ajax() not implemented");
+        var obj = ajaxImpl(options, exports);
+        var req = response(delegate, obj);
+        req.addEventListener(
+          "load",
+          function onLoad() {
+            var response = JSON.parse(req.responseText);
+            if (!response.error)
+              options.success(response);
+          },
+          false
+        );
+        return req;
       };
     };
 
@@ -88,7 +191,7 @@
 
     self.mockTriggerEvent = function(event) {
       verifyEventType(event.type);
-      listeners.forEach(
+      listeners[event.type].forEach(
         function(listener) {
           listener(event);
         });