# HG changeset patch # User Atul Varma # Date 1272434789 25200 # Node ID c486d35fad270153a08e3a15274b86543831e170 # Parent 544d339d2b4c898a2bd253c14d099b31404dec03 added more mocks; black-box now talks to a really simple fake bugzilla 'server'. diff -r 544d339d2b4c -r c486d35fad27 js/black-box.js --- 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"); }; diff -r 544d339d2b4c -r c486d35fad27 js/modules/mocks.js --- 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); });