Commit 0bc11eda authored by Romain Courteaud's avatar Romain Courteaud

One failing declareGadget should not breaks the next calls.

parent 2d34d987
/*! RenderJs */
/*
* DOMParser HTML extension
* 2012-09-04
*
* By Eli Grey, http://eligrey.com
* Public domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/
/*! @source https://gist.github.com/1129031 */
(function (DOMParser) {
"use strict";
var DOMParser_proto = DOMParser.prototype,
real_parseFromString = DOMParser_proto.parseFromString;
// Firefox/Opera/IE throw errors on unsupported types
try {
// WebKit returns null on unsupported types
if ((new DOMParser()).parseFromString("", "text/html")) {
// text/html parsing is natively supported
return;
}
} catch (ignore) {}
DOMParser_proto.parseFromString = function (markup, type) {
var result, doc, doc_elt, first_elt;
if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
doc = document.implementation.createHTMLDocument("");
doc_elt = doc.documentElement;
doc_elt.innerHTML = markup;
first_elt = doc_elt.firstElementChild;
if (doc_elt.childElementCount === 1
&& first_elt.localName.toLowerCase() === "html") {
doc.replaceChild(first_elt, doc_elt);
}
result = doc;
} else {
result = real_parseFromString.apply(this, arguments);
}
return result;
};
}(DOMParser));
/*
* renderJs - Generic Gadget library renderer.
* http://www.renderjs.org/documentation
*/
(function (document, window, RSVP, DOMParser, Channel, undefined) {
"use strict";
var gadget_model_dict = {},
javascript_registration_dict = {},
stylesheet_registration_dict = {},
gadget_loading_klass,
loading_gadget_promise,
renderJS;
/////////////////////////////////////////////////////////////////
// RenderJSGadget
/////////////////////////////////////////////////////////////////
function RenderJSGadget() {
if (!(this instanceof RenderJSGadget)) {
return new RenderJSGadget();
}
}
RenderJSGadget.prototype.title = "";
RenderJSGadget.prototype.interface_list = [];
RenderJSGadget.prototype.path = "";
RenderJSGadget.prototype.html = "";
RenderJSGadget.prototype.required_css_list = [];
RenderJSGadget.prototype.required_js_list = [];
RenderJSGadget.ready_list = [];
RenderJSGadget.ready = function (callback) {
this.ready_list.push(callback);
return this;
};
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareMethod
/////////////////////////////////////////////////////////////////
RenderJSGadget.declareMethod = function (name, callback) {
this.prototype[name] = function () {
var context = this,
argument_list = arguments;
return new RSVP.Queue()
.push(function () {
return callback.apply(context, argument_list);
});
};
// Allow chain
return this;
};
RenderJSGadget
.declareMethod('getInterfaceList', function () {
// Returns the list of gadget prototype
return this.interface_list;
})
.declareMethod('getRequiredCSSList', function () {
// Returns a list of CSS required by the gadget
return this.required_css_list;
})
.declareMethod('getRequiredJSList', function () {
// Returns a list of JS required by the gadget
return this.required_js_list;
})
.declareMethod('getPath', function () {
// Returns the path of the code of a gadget
return this.path;
})
.declareMethod('getTitle', function () {
// Returns the title of a gadget
return this.title;
})
.declareMethod('getElement', function () {
// Returns the DOM Element of a gadget
if (this.element === undefined) {
throw new Error("No element defined");
}
return this.element;
});
/////////////////////////////////////////////////////////////////
// RenderJSEmbeddedGadget
/////////////////////////////////////////////////////////////////
// Class inheritance
function RenderJSEmbeddedGadget() {
if (!(this instanceof RenderJSEmbeddedGadget)) {
return new RenderJSEmbeddedGadget();
}
RenderJSGadget.call(this);
}
RenderJSEmbeddedGadget.ready_list = [];
RenderJSEmbeddedGadget.ready =
RenderJSGadget.ready;
RenderJSEmbeddedGadget.prototype = new RenderJSGadget();
RenderJSEmbeddedGadget.prototype.constructor = RenderJSEmbeddedGadget;
/////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget
/////////////////////////////////////////////////////////////////
function privateDeclarePublicGadget(url, options) {
var gadget_instance;
if (options.element === undefined) {
options.element = document.createElement("div");
}
return new RSVP.Queue()
.push(function () {
return renderJS.declareGadgetKlass(url);
})
// Get the gadget class and instanciate it
.push(function (Klass) {
var i,
template_node_list = Klass.template_element.body.childNodes;
gadget_loading_klass = Klass;
gadget_instance = new Klass();
gadget_instance.element = options.element;
for (i = 0; i < template_node_list.length; i += 1) {
gadget_instance.element.appendChild(
template_node_list[i].cloneNode(true)
);
}
// Load dependencies if needed
return RSVP.all([
gadget_instance.getRequiredJSList(),
gadget_instance.getRequiredCSSList()
]);
})
// Load all JS/CSS
.push(function (all_list) {
var parameter_list = [],
i;
// Load JS
for (i = 0; i < all_list[0].length; i += 1) {
parameter_list.push(renderJS.declareJS(all_list[0][i]));
}
// Load CSS
for (i = 0; i < all_list[1].length; i += 1) {
parameter_list.push(renderJS.declareCSS(all_list[1][i]));
}
return RSVP.all(parameter_list);
})
.push(function () {
return gadget_instance;
});
}
/////////////////////////////////////////////////////////////////
// RenderJSIframeGadget
/////////////////////////////////////////////////////////////////
function RenderJSIframeGadget() {
if (!(this instanceof RenderJSIframeGadget)) {
return new RenderJSIframeGadget();
}
RenderJSGadget.call(this);
}
RenderJSIframeGadget.ready_list = [];
RenderJSIframeGadget.ready =
RenderJSGadget.ready;
RenderJSIframeGadget.prototype = new RenderJSGadget();
RenderJSIframeGadget.prototype.constructor = RenderJSIframeGadget;
/////////////////////////////////////////////////////////////////
// privateDeclareIframeGadget
/////////////////////////////////////////////////////////////////
function privateDeclareIframeGadget(url, options) {
var gadget_instance,
iframe,
node,
iframe_loading_deferred = RSVP.defer();
if (options.element === undefined) {
throw new Error("DOM element is required to create Iframe Gadget " +
url);
}
// Check if the element is attached to the DOM
node = options.element.parentNode;
while (node !== null) {
if (node === document) {
break;
}
node = node.parentNode;
}
if (node === null) {
throw new Error("The parent element is not attached to the DOM for " +
url);
}
gadget_instance = new RenderJSIframeGadget();
iframe = document.createElement("iframe");
// gadget_instance.element.setAttribute("seamless", "seamless");
iframe.setAttribute("src", url);
gadget_instance.path = url;
gadget_instance.element = options.element;
// Attach it to the DOM
options.element.appendChild(iframe);
// XXX Manage unbind when deleting the gadget
// Create the communication channel with the iframe
gadget_instance.chan = Channel.build({
window: iframe.contentWindow,
origin: "*",
scope: "renderJS"
});
// Create new method from the declareMethod call inside the iframe
gadget_instance.chan.bind("declareMethod", function (trans, method_name) {
gadget_instance[method_name] = function () {
var argument_list = arguments;
return new RSVP.Promise(function (resolve, reject) {
gadget_instance.chan.call({
method: "methodCall",
params: [
method_name,
Array.prototype.slice.call(argument_list, 0)],
success: function (s) {
resolve(s);
},
error: function (e) {
reject(e);
}
});
});
};
return "OK";
});
// Wait for the iframe to be loaded before continuing
gadget_instance.chan.bind("ready", function (trans) {
iframe_loading_deferred.resolve(gadget_instance);
return "OK";
});
gadget_instance.chan.bind("failed", function (trans, params) {
iframe_loading_deferred.reject(params);
return "OK";
});
return RSVP.any([
iframe_loading_deferred.promise,
// Timeout to prevent non renderJS embeddable gadget
// XXX Maybe using iframe.onload/onerror would be safer?
RSVP.timeout(5000)
]);
}
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget
/////////////////////////////////////////////////////////////////
RenderJSGadget.prototype.declareGadget = function (url, options) {
var queue,
previous_loading_gadget_promise = loading_gadget_promise;
if (options === undefined) {
options = {};
}
if (options.sandbox === undefined) {
options.sandbox = "public";
}
// Change the global variable to update the loading queue
queue = new RSVP.Queue()
// Wait for previous gadget loading to finish first
.push(function () {
return previous_loading_gadget_promise;
})
.push(undefined, function () {
// Forget previous declareGadget error
return;
})
.push(function () {
var method;
if (options.sandbox === "public") {
method = privateDeclarePublicGadget;
} else if (options.sandbox === "iframe") {
method = privateDeclareIframeGadget;
} else {
throw new Error("Unsupported sandbox options '" +
options.sandbox + "'");
}
return method(url, options);
})
// Set the HTML context
.push(function (gadget_instance) {
var i;
// Drop the current loading klass info used by selector
gadget_loading_klass = undefined;
// Trigger calling of all ready callback
function ready_wrapper() {
return gadget_instance;
}
for (i = 0; i < gadget_instance.constructor.ready_list.length;
i += 1) {
// Put a timeout?
queue.push(gadget_instance.constructor.ready_list[i]);
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
}
return gadget_instance;
})
.push(undefined, function (e) {
// Drop the current loading klass info used by selector
// even in case of error
gadget_loading_klass = undefined;
throw e;
});
loading_gadget_promise = queue;
return loading_gadget_promise;
};
/////////////////////////////////////////////////////////////////
// renderJS selector
/////////////////////////////////////////////////////////////////
renderJS = function (selector) {
var result;
if (selector === window) {
// window is the 'this' value when loading a javascript file
// In this case, use the current loading gadget constructor
result = gadget_loading_klass;
} else if (selector instanceof RenderJSGadget) {
result = selector;
}
if (result === undefined) {
throw new Error("Unknown selector '" + selector + "'");
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareJS
/////////////////////////////////////////////////////////////////
renderJS.declareJS = function (url) {
// Prevent infinite recursion if loading render.js
// more than once
var result;
if (javascript_registration_dict.hasOwnProperty(url)) {
result = RSVP.resolve();
} else {
result = new RSVP.Promise(function (resolve, reject) {
var newScript;
newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = url;
newScript.onload = function () {
javascript_registration_dict[url] = null;
resolve();
};
newScript.onerror = function (e) {
reject(e);
};
document.head.appendChild(newScript);
});
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareCSS
/////////////////////////////////////////////////////////////////
renderJS.declareCSS = function (url) {
// https://github.com/furf/jquery-getCSS/blob/master/jquery.getCSS.js
// No way to cleanly check if a css has been loaded
// So, always resolve the promise...
// http://requirejs.org/docs/faq-advanced.html#css
var result;
if (stylesheet_registration_dict.hasOwnProperty(url)) {
result = RSVP.resolve();
} else {
result = new RSVP.Promise(function (resolve, reject) {
var link;
link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = url;
link.onload = function () {
stylesheet_registration_dict[url] = null;
resolve();
};
link.onerror = function (e) {
reject(e);
};
document.head.appendChild(link);
});
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareGadgetKlass
/////////////////////////////////////////////////////////////////
renderJS.declareGadgetKlass = function (url) {
var result,
xhr;
function parse() {
var tmp_constructor,
key,
parsed_html;
if (!gadget_model_dict.hasOwnProperty(url)) {
// Class inheritance
tmp_constructor = function () {
RenderJSGadget.call(this);
};
tmp_constructor.ready_list = [];
tmp_constructor.declareMethod =
RenderJSGadget.declareMethod;
tmp_constructor.ready =
RenderJSGadget.ready;
tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.path = url;
// https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest
// https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
// https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM
tmp_constructor.template_element =
(new DOMParser()).parseFromString(xhr.responseText, "text/html");
parsed_html = renderJS.parseGadgetHTMLDocument(
tmp_constructor.template_element
);
for (key in parsed_html) {
if (parsed_html.hasOwnProperty(key)) {
tmp_constructor.prototype[key] = parsed_html[key];
}
}
gadget_model_dict[url] = tmp_constructor;
}
return gadget_model_dict[url];
}
function resolver(resolve, reject) {
function handler() {
var tmp_result;
try {
if (xhr.readyState === 0) {
// UNSENT
reject(xhr);
} else if (xhr.readyState === 4) {
// DONE
if ((xhr.status < 200) || (xhr.status >= 300) ||
(!/^text\/html[;]?/.test(
xhr.getResponseHeader("Content-Type") || ""
))) {
reject(xhr);
} else {
tmp_result = parse();
resolve(tmp_result);
}
}
} catch (e) {
reject(e);
}
}
xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = handler;
xhr.setRequestHeader('Accept', 'text/html');
xhr.withCredentials = true;
xhr.send();
}
function canceller() {
if ((xhr !== undefined) && (xhr.readyState !== xhr.DONE)) {
xhr.abort();
}
}
if (gadget_model_dict.hasOwnProperty(url)) {
// Return klass object if it already exists
result = RSVP.resolve(gadget_model_dict[url]);
} else {
// Fetch the HTML page and parse it
result = new RSVP.Promise(resolver, canceller);
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.clearGadgetKlassList
/////////////////////////////////////////////////////////////////
// For test purpose only
renderJS.clearGadgetKlassList = function () {
gadget_model_dict = {};
javascript_registration_dict = {};
stylesheet_registration_dict = {};
};
/////////////////////////////////////////////////////////////////
// renderJS.parseGadgetHTMLDocument
/////////////////////////////////////////////////////////////////
renderJS.parseGadgetHTMLDocument = function (document_element) {
var settings = {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: []
},
i,
element;
if (document_element.nodeType === 9) {
settings.title = document_element.title;
for (i = 0; i < document_element.head.children.length; i += 1) {
element = document_element.head.children[i];
if (element.href !== null) {
// XXX Manage relative URL during extraction of URLs
// element.href returns absolute URL in firefox but "" in chrome;
if (element.rel === "stylesheet") {
settings.required_css_list.push(element.getAttribute("href"));
} else if (element.type === "text/javascript") {
settings.required_js_list.push(element.getAttribute("src"));
} else if (element.rel === "http://www.renderjs.org/rel/interface") {
settings.interface_list.push(element.getAttribute("href"));
}
}
}
} else {
throw new Error("The first parameter should be an HTMLDocument");
}
return settings;
};
/////////////////////////////////////////////////////////////////
// global
/////////////////////////////////////////////////////////////////
window.rJS = window.renderJS = renderJS;
window.RenderJSGadget = RenderJSGadget;
window.RenderJSEmbeddedGadget = RenderJSEmbeddedGadget;
window.RenderJSIframeGadget = RenderJSIframeGadget;
///////////////////////////////////////////////////
// Bootstrap process. Register the self gadget.
///////////////////////////////////////////////////
function bootstrap() {
var url = window.location.href,
tmp_constructor,
root_gadget,
declare_method_count = 0,
embedded_channel,
notifyReady,
notifyDeclareMethod,
gadget_ready = false;
// Create the gadget class for the current url
if (gadget_model_dict.hasOwnProperty(url)) {
throw new Error("bootstrap should not be called twice");
}
loading_gadget_promise = new RSVP.Promise(function (resolve, reject) {
if (window.self === window.top) {
// XXX Copy/Paste from declareGadgetKlass
tmp_constructor = function () {
RenderJSGadget.call(this);
};
tmp_constructor.declareMethod = RenderJSGadget.declareMethod;
tmp_constructor.ready_list = [];
tmp_constructor.ready = RenderJSGadget.ready;
tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.path = url;
gadget_model_dict[url] = tmp_constructor;
// Create the root gadget instance and put it in the loading stack
root_gadget = new gadget_model_dict[url]();
} else {
// Create the communication channel
embedded_channel = Channel.build({
window: window.parent,
origin: "*",
scope: "renderJS"
});
// Create the root gadget instance and put it in the loading stack
tmp_constructor = RenderJSEmbeddedGadget;
root_gadget = new RenderJSEmbeddedGadget();
// Bind calls to renderJS method on the instance
embedded_channel.bind("methodCall", function (trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1]).then(function (g) {
trans.complete(g);
}).fail(function (e) {
trans.error(e.toString());
});
trans.delayReturn(true);
});
// Notify parent about gadget instanciation
notifyReady = function () {
if ((declare_method_count === 0) && (gadget_ready === true)) {
embedded_channel.notify({method: "ready"});
}
};
// Inform parent gadget about declareMethod calls here.
notifyDeclareMethod = function (name) {
declare_method_count += 1;
embedded_channel.call({
method: "declareMethod",
params: name,
success: function () {
declare_method_count -= 1;
notifyReady();
},
error: function () {
declare_method_count -= 1;
}
});
};
notifyDeclareMethod("getInterfaceList");
notifyDeclareMethod("getRequiredCSSList");
notifyDeclareMethod("getRequiredJSList");
notifyDeclareMethod("getPath");
notifyDeclareMethod("getTitle");
// Surcharge declareMethod to inform parent window
tmp_constructor.declareMethod = function (name, callback) {
var result = RenderJSGadget.declareMethod.apply(
this,
[name, callback]
);
notifyDeclareMethod(name);
return result;
};
}
gadget_loading_klass = tmp_constructor;
function init() {
// XXX HTML properties can only be set when the DOM is fully loaded
var settings = renderJS.parseGadgetHTMLDocument(document),
j,
key;
for (key in settings) {
if (settings.hasOwnProperty(key)) {
tmp_constructor.prototype[key] = settings[key];
}
}
tmp_constructor.template_element = document.createElement("div");
root_gadget.element = document.body;
for (j = 0; j < root_gadget.element.childNodes.length; j += 1) {
tmp_constructor.template_element.appendChild(
root_gadget.element.childNodes[j].cloneNode(true)
);
}
RSVP.all([root_gadget.getRequiredJSList(),
root_gadget.getRequiredCSSList()])
.then(function (all_list) {
var i,
js_list = all_list[0],
css_list = all_list[1],
queue;
for (i = 0; i < js_list.length; i += 1) {
javascript_registration_dict[js_list[i]] = null;
}
for (i = 0; i < css_list.length; i += 1) {
stylesheet_registration_dict[css_list[i]] = null;
}
gadget_loading_klass = undefined;
queue = new RSVP.Queue();
function ready_wrapper() {
return root_gadget;
}
queue.push(ready_wrapper);
for (i = 0; i < tmp_constructor.ready_list.length; i += 1) {
// Put a timeout?
queue.push(tmp_constructor.ready_list[i]);
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
}
queue.push(resolve, function (e) {
reject(e);
throw e;
});
return queue;
}).fail(function (e) {
reject(e);
});
}
document.addEventListener('DOMContentLoaded', init, false);
});
if (window.self !== window.top) {
// Inform parent window that gadget is correctly loaded
loading_gadget_promise.then(function () {
gadget_ready = true;
notifyReady();
}).fail(function (e) {
embedded_channel.notify({method: "failed", params: e.toString()});
throw e;
});
}
}
bootstrap();
}(document, window, RSVP, DOMParser, Channel));
!function(a){"use strict";var b=a.prototype,c=b.parseFromString;try{if((new a).parseFromString("","text/html"))return}catch(d){}b.parseFromString=function(a,b){var d,e,f,g;return/^\s*text\/html\s*(?:;|$)/i.test(b)?(e=document.implementation.createHTMLDocument(""),f=e.documentElement,f.innerHTML=a,g=f.firstElementChild,1===f.childElementCount&&"html"===g.localName.toLowerCase()&&e.replaceChild(g,f),d=e):d=c.apply(this,arguments),d}}(DOMParser),function(a,b,c,d,e,f){"use strict";function g(){return this instanceof g?void 0:new g}function h(){return this instanceof h?(g.call(this),void 0):new h}function i(b,d){var e;return d.element===f&&(d.element=a.createElement("div")),(new c.Queue).push(function(){return o.declareGadgetKlass(b)}).push(function(a){var b,f=a.template_element.body.childNodes;for(m=a,e=new a,e.element=d.element,b=0;b<f.length;b+=1)e.element.appendChild(f[b].cloneNode(!0));return c.all([e.getRequiredJSList(),e.getRequiredCSSList()])}).push(function(a){var b,d=[];for(b=0;b<a[0].length;b+=1)d.push(o.declareJS(a[0][b]));for(b=0;b<a[1].length;b+=1)d.push(o.declareCSS(a[1][b]));return c.all(d)}).push(function(){return e})}function j(){return this instanceof j?(g.call(this),void 0):new j}function k(b,d){var g,h,i,k=c.defer();if(d.element===f)throw new Error("DOM element is required to create Iframe Gadget "+b);for(i=d.element.parentNode;null!==i&&i!==a;)i=i.parentNode;if(null===i)throw new Error("The parent element is not attached to the DOM for "+b);return g=new j,h=a.createElement("iframe"),h.setAttribute("src",b),g.path=b,g.element=d.element,d.element.appendChild(h),g.chan=e.build({window:h.contentWindow,origin:"*",scope:"renderJS"}),g.chan.bind("declareMethod",function(a,b){return g[b]=function(){var a=arguments;return new c.Promise(function(c,d){g.chan.call({method:"methodCall",params:[b,Array.prototype.slice.call(a,0)],success:function(a){c(a)},error:function(a){d(a)}})})},"OK"}),g.chan.bind("ready",function(){return k.resolve(g),"OK"}),g.chan.bind("failed",function(a,b){return k.reject(b),"OK"}),c.any([k.promise,c.timeout(5e3)])}function l(){var d,i,j,k,l,s=b.location.href,t=0,u=!1;if(p.hasOwnProperty(s))throw new Error("bootstrap should not be called twice");n=new c.Promise(function(n,v){function w(){var b,e,g=o.parseGadgetHTMLDocument(a);for(e in g)g.hasOwnProperty(e)&&(d.prototype[e]=g[e]);for(d.template_element=a.createElement("div"),i.element=a.body,b=0;b<i.element.childNodes.length;b+=1)d.template_element.appendChild(i.element.childNodes[b].cloneNode(!0));c.all([i.getRequiredJSList(),i.getRequiredCSSList()]).then(function(a){function b(){return i}var e,g,h=a[0],j=a[1];for(e=0;e<h.length;e+=1)q[h[e]]=null;for(e=0;e<j.length;e+=1)r[j[e]]=null;for(m=f,g=new c.Queue,g.push(b),e=0;e<d.ready_list.length;e+=1)g.push(d.ready_list[e]),g.push(b);return g.push(n,function(a){throw v(a),a}),g}).fail(function(a){v(a)})}b.self===b.top?(d=function(){g.call(this)},d.declareMethod=g.declareMethod,d.ready_list=[],d.ready=g.ready,d.prototype=new g,d.prototype.constructor=d,d.prototype.path=s,p[s]=d,i=new p[s]):(j=e.build({window:b.parent,origin:"*",scope:"renderJS"}),d=h,i=new h,j.bind("methodCall",function(a,b){i[b[0]].apply(i,b[1]).then(function(b){a.complete(b)}).fail(function(b){a.error(b.toString())}),a.delayReturn(!0)}),k=function(){0===t&&u===!0&&j.notify({method:"ready"})},l=function(a){t+=1,j.call({method:"declareMethod",params:a,success:function(){t-=1,k()},error:function(){t-=1}})},l("getInterfaceList"),l("getRequiredCSSList"),l("getRequiredJSList"),l("getPath"),l("getTitle"),d.declareMethod=function(a,b){var c=g.declareMethod.apply(this,[a,b]);return l(a),c}),m=d,a.addEventListener("DOMContentLoaded",w,!1)}),b.self!==b.top&&n.then(function(){u=!0,k()}).fail(function(a){throw j.notify({method:"failed",params:a.toString()}),a})}var m,n,o,p={},q={},r={};g.prototype.title="",g.prototype.interface_list=[],g.prototype.path="",g.prototype.html="",g.prototype.required_css_list=[],g.prototype.required_js_list=[],g.ready_list=[],g.ready=function(a){return this.ready_list.push(a),this},g.declareMethod=function(a,b){return this.prototype[a]=function(){var a=this,d=arguments;return(new c.Queue).push(function(){return b.apply(a,d)})},this},g.declareMethod("getInterfaceList",function(){return this.interface_list}).declareMethod("getRequiredCSSList",function(){return this.required_css_list}).declareMethod("getRequiredJSList",function(){return this.required_js_list}).declareMethod("getPath",function(){return this.path}).declareMethod("getTitle",function(){return this.title}).declareMethod("getElement",function(){if(this.element===f)throw new Error("No element defined");return this.element}),h.ready_list=[],h.ready=g.ready,h.prototype=new g,h.prototype.constructor=h,j.ready_list=[],j.ready=g.ready,j.prototype=new g,j.prototype.constructor=j,g.prototype.declareGadget=function(a,b){var d,e=n;return b===f&&(b={}),b.sandbox===f&&(b.sandbox="public"),d=(new c.Queue).push(function(){return e}).push(f,function(){}).push(function(){var c;if("public"===b.sandbox)c=i;else{if("iframe"!==b.sandbox)throw new Error("Unsupported sandbox options '"+b.sandbox+"'");c=k}return c(a,b)}).push(function(a){function b(){return a}var c;for(m=f,c=0;c<a.constructor.ready_list.length;c+=1)d.push(a.constructor.ready_list[c]),d.push(b);return a}).push(f,function(a){throw m=f,a}),n=d},o=function(a){var c;if(a===b?c=m:a instanceof g&&(c=a),c===f)throw new Error("Unknown selector '"+a+"'");return c},o.declareJS=function(b){var d;return d=q.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("script"),e.type="text/javascript",e.src=b,e.onload=function(){q[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareCSS=function(b){var d;return d=r.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("link"),e.rel="stylesheet",e.type="text/css",e.href=b,e.onload=function(){r[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareGadgetKlass=function(a){function b(){var b,c,e;if(!p.hasOwnProperty(a)){b=function(){g.call(this)},b.ready_list=[],b.declareMethod=g.declareMethod,b.ready=g.ready,b.prototype=new g,b.prototype.constructor=b,b.prototype.path=a,b.template_element=(new d).parseFromString(j.responseText,"text/html"),e=o.parseGadgetHTMLDocument(b.template_element);for(c in e)e.hasOwnProperty(c)&&(b.prototype[c]=e[c]);p[a]=b}return p[a]}function e(c,d){function e(){var a;try{0===j.readyState?d(j):4===j.readyState&&(j.status<200||j.status>=300||!/^text\/html[;]?/.test(j.getResponseHeader("Content-Type")||"")?d(j):(a=b(),c(a)))}catch(e){d(e)}}j=new XMLHttpRequest,j.open("GET",a),j.onreadystatechange=e,j.setRequestHeader("Accept","text/html"),j.withCredentials=!0,j.send()}function h(){j!==f&&j.readyState!==j.DONE&&j.abort()}var i,j;return i=p.hasOwnProperty(a)?c.resolve(p[a]):new c.Promise(e,h)},o.clearGadgetKlassList=function(){p={},q={},r={}},o.parseGadgetHTMLDocument=function(a){var b,c,d={title:"",interface_list:[],required_css_list:[],required_js_list:[]};if(9!==a.nodeType)throw new Error("The first parameter should be an HTMLDocument");for(d.title=a.title,b=0;b<a.head.children.length;b+=1)c=a.head.children[b],null!==c.href&&("stylesheet"===c.rel?d.required_css_list.push(c.getAttribute("href")):"text/javascript"===c.type?d.required_js_list.push(c.getAttribute("src")):"http://www.renderjs.org/rel/interface"===c.rel&&d.interface_list.push(c.getAttribute("href")));return d},b.rJS=b.renderJS=o,b.RenderJSGadget=g,b.RenderJSEmbeddedGadget=h,b.RenderJSIframeGadget=j,l()}(document,window,RSVP,DOMParser,Channel);
\ No newline at end of file
/*! RenderJs v0.3.2 */
/*! RenderJs */
/*
* DOMParser HTML extension
......@@ -311,6 +311,10 @@
.push(function () {
return previous_loading_gadget_promise;
})
.push(undefined, function () {
// Forget previous declareGadget error
return;
})
.push(function () {
var method;
if (options.sandbox === "public") {
......
!function(a){"use strict";var b=a.prototype,c=b.parseFromString;try{if((new a).parseFromString("","text/html"))return}catch(d){}b.parseFromString=function(a,b){var d,e,f,g;return/^\s*text\/html\s*(?:;|$)/i.test(b)?(e=document.implementation.createHTMLDocument(""),f=e.documentElement,f.innerHTML=a,g=f.firstElementChild,1===f.childElementCount&&"html"===g.localName.toLowerCase()&&e.replaceChild(g,f),d=e):d=c.apply(this,arguments),d}}(DOMParser),function(a,b,c,d,e,f){"use strict";function g(){return this instanceof g?void 0:new g}function h(){return this instanceof h?(g.call(this),void 0):new h}function i(b,d){var e;return d.element===f&&(d.element=a.createElement("div")),(new c.Queue).push(function(){return o.declareGadgetKlass(b)}).push(function(a){var b,f=a.template_element.body.childNodes;for(m=a,e=new a,e.element=d.element,b=0;b<f.length;b+=1)e.element.appendChild(f[b].cloneNode(!0));return c.all([e.getRequiredJSList(),e.getRequiredCSSList()])}).push(function(a){var b,d=[];for(b=0;b<a[0].length;b+=1)d.push(o.declareJS(a[0][b]));for(b=0;b<a[1].length;b+=1)d.push(o.declareCSS(a[1][b]));return c.all(d)}).push(function(){return e})}function j(){return this instanceof j?(g.call(this),void 0):new j}function k(b,d){var g,h,i,k=c.defer();if(d.element===f)throw new Error("DOM element is required to create Iframe Gadget "+b);for(i=d.element.parentNode;null!==i&&i!==a;)i=i.parentNode;if(null===i)throw new Error("The parent element is not attached to the DOM for "+b);return g=new j,h=a.createElement("iframe"),h.setAttribute("src",b),g.path=b,g.element=d.element,d.element.appendChild(h),g.chan=e.build({window:h.contentWindow,origin:"*",scope:"renderJS"}),g.chan.bind("declareMethod",function(a,b){return g[b]=function(){var a=arguments;return new c.Promise(function(c,d){g.chan.call({method:"methodCall",params:[b,Array.prototype.slice.call(a,0)],success:function(a){c(a)},error:function(a){d(a)}})})},"OK"}),g.chan.bind("ready",function(){return k.resolve(g),"OK"}),g.chan.bind("failed",function(a,b){return k.reject(b),"OK"}),c.any([k.promise,c.timeout(5e3)])}function l(){var d,i,j,k,l,s=b.location.href,t=0,u=!1;if(p.hasOwnProperty(s))throw new Error("bootstrap should not be called twice");n=new c.Promise(function(n,v){function w(){var b,e,g=o.parseGadgetHTMLDocument(a);for(e in g)g.hasOwnProperty(e)&&(d.prototype[e]=g[e]);for(d.template_element=a.createElement("div"),i.element=a.body,b=0;b<i.element.childNodes.length;b+=1)d.template_element.appendChild(i.element.childNodes[b].cloneNode(!0));c.all([i.getRequiredJSList(),i.getRequiredCSSList()]).then(function(a){function b(){return i}var e,g,h=a[0],j=a[1];for(e=0;e<h.length;e+=1)q[h[e]]=null;for(e=0;e<j.length;e+=1)r[j[e]]=null;for(m=f,g=new c.Queue,g.push(b),e=0;e<d.ready_list.length;e+=1)g.push(d.ready_list[e]),g.push(b);return g.push(n,function(a){throw v(a),a}),g}).fail(function(a){v(a)})}b.self===b.top?(d=function(){g.call(this)},d.declareMethod=g.declareMethod,d.ready_list=[],d.ready=g.ready,d.prototype=new g,d.prototype.constructor=d,d.prototype.path=s,p[s]=d,i=new p[s]):(j=e.build({window:b.parent,origin:"*",scope:"renderJS"}),d=h,i=new h,j.bind("methodCall",function(a,b){i[b[0]].apply(i,b[1]).then(function(b){a.complete(b)}).fail(function(b){a.error(b.toString())}),a.delayReturn(!0)}),k=function(){0===t&&u===!0&&j.notify({method:"ready"})},l=function(a){t+=1,j.call({method:"declareMethod",params:a,success:function(){t-=1,k()},error:function(){t-=1}})},l("getInterfaceList"),l("getRequiredCSSList"),l("getRequiredJSList"),l("getPath"),l("getTitle"),d.declareMethod=function(a,b){var c=g.declareMethod.apply(this,[a,b]);return l(a),c}),m=d,a.addEventListener("DOMContentLoaded",w,!1)}),b.self!==b.top&&n.then(function(){u=!0,k()}).fail(function(a){throw j.notify({method:"failed",params:a.toString()}),a})}var m,n,o,p={},q={},r={};g.prototype.title="",g.prototype.interface_list=[],g.prototype.path="",g.prototype.html="",g.prototype.required_css_list=[],g.prototype.required_js_list=[],g.ready_list=[],g.ready=function(a){return this.ready_list.push(a),this},g.declareMethod=function(a,b){return this.prototype[a]=function(){var a=this,d=arguments;return(new c.Queue).push(function(){return b.apply(a,d)})},this},g.declareMethod("getInterfaceList",function(){return this.interface_list}).declareMethod("getRequiredCSSList",function(){return this.required_css_list}).declareMethod("getRequiredJSList",function(){return this.required_js_list}).declareMethod("getPath",function(){return this.path}).declareMethod("getTitle",function(){return this.title}).declareMethod("getElement",function(){if(this.element===f)throw new Error("No element defined");return this.element}),h.ready_list=[],h.ready=g.ready,h.prototype=new g,h.prototype.constructor=h,j.ready_list=[],j.ready=g.ready,j.prototype=new g,j.prototype.constructor=j,g.prototype.declareGadget=function(a,b){var d,e=n;return b===f&&(b={}),b.sandbox===f&&(b.sandbox="public"),d=(new c.Queue).push(function(){return e}).push(function(){var c;if("public"===b.sandbox)c=i;else{if("iframe"!==b.sandbox)throw new Error("Unsupported sandbox options '"+b.sandbox+"'");c=k}return c(a,b)}).push(function(a){function b(){return a}var c;for(m=f,c=0;c<a.constructor.ready_list.length;c+=1)d.push(a.constructor.ready_list[c]),d.push(b);return a}).push(f,function(a){throw m=f,a}),n=d},o=function(a){var c;if(a===b?c=m:a instanceof g&&(c=a),c===f)throw new Error("Unknown selector '"+a+"'");return c},o.declareJS=function(b){var d;return d=q.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("script"),e.type="text/javascript",e.src=b,e.onload=function(){q[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareCSS=function(b){var d;return d=r.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("link"),e.rel="stylesheet",e.type="text/css",e.href=b,e.onload=function(){r[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareGadgetKlass=function(a){function b(){var b,c,e;if(!p.hasOwnProperty(a)){b=function(){g.call(this)},b.ready_list=[],b.declareMethod=g.declareMethod,b.ready=g.ready,b.prototype=new g,b.prototype.constructor=b,b.prototype.path=a,b.template_element=(new d).parseFromString(j.responseText,"text/html"),e=o.parseGadgetHTMLDocument(b.template_element);for(c in e)e.hasOwnProperty(c)&&(b.prototype[c]=e[c]);p[a]=b}return p[a]}function e(c,d){function e(){var a;try{0===j.readyState?d(j):4===j.readyState&&(j.status<200||j.status>=300||!/^text\/html[;]?/.test(j.getResponseHeader("Content-Type")||"")?d(j):(a=b(),c(a)))}catch(e){d(e)}}j=new XMLHttpRequest,j.open("GET",a),j.onreadystatechange=e,j.setRequestHeader("Accept","text/html"),j.withCredentials=!0,j.send()}function h(){j!==f&&j.readyState!==j.DONE&&j.abort()}var i,j;return i=p.hasOwnProperty(a)?c.resolve(p[a]):new c.Promise(e,h)},o.clearGadgetKlassList=function(){p={},q={},r={}},o.parseGadgetHTMLDocument=function(a){var b,c,d={title:"",interface_list:[],required_css_list:[],required_js_list:[]};if(9!==a.nodeType)throw new Error("The first parameter should be an HTMLDocument");for(d.title=a.title,b=0;b<a.head.children.length;b+=1)c=a.head.children[b],null!==c.href&&("stylesheet"===c.rel?d.required_css_list.push(c.getAttribute("href")):"text/javascript"===c.type?d.required_js_list.push(c.getAttribute("src")):"http://www.renderjs.org/rel/interface"===c.rel&&d.interface_list.push(c.getAttribute("href")));return d},b.rJS=b.renderJS=o,b.RenderJSGadget=g,b.RenderJSEmbeddedGadget=h,b.RenderJSIframeGadget=j,l()}(document,window,RSVP,DOMParser,Channel);
\ No newline at end of file
!function(a){"use strict";var b=a.prototype,c=b.parseFromString;try{if((new a).parseFromString("","text/html"))return}catch(d){}b.parseFromString=function(a,b){var d,e,f,g;return/^\s*text\/html\s*(?:;|$)/i.test(b)?(e=document.implementation.createHTMLDocument(""),f=e.documentElement,f.innerHTML=a,g=f.firstElementChild,1===f.childElementCount&&"html"===g.localName.toLowerCase()&&e.replaceChild(g,f),d=e):d=c.apply(this,arguments),d}}(DOMParser),function(a,b,c,d,e,f){"use strict";function g(){return this instanceof g?void 0:new g}function h(){return this instanceof h?(g.call(this),void 0):new h}function i(b,d){var e;return d.element===f&&(d.element=a.createElement("div")),(new c.Queue).push(function(){return o.declareGadgetKlass(b)}).push(function(a){var b,f=a.template_element.body.childNodes;for(m=a,e=new a,e.element=d.element,b=0;b<f.length;b+=1)e.element.appendChild(f[b].cloneNode(!0));return c.all([e.getRequiredJSList(),e.getRequiredCSSList()])}).push(function(a){var b,d=[];for(b=0;b<a[0].length;b+=1)d.push(o.declareJS(a[0][b]));for(b=0;b<a[1].length;b+=1)d.push(o.declareCSS(a[1][b]));return c.all(d)}).push(function(){return e})}function j(){return this instanceof j?(g.call(this),void 0):new j}function k(b,d){var g,h,i,k=c.defer();if(d.element===f)throw new Error("DOM element is required to create Iframe Gadget "+b);for(i=d.element.parentNode;null!==i&&i!==a;)i=i.parentNode;if(null===i)throw new Error("The parent element is not attached to the DOM for "+b);return g=new j,h=a.createElement("iframe"),h.setAttribute("src",b),g.path=b,g.element=d.element,d.element.appendChild(h),g.chan=e.build({window:h.contentWindow,origin:"*",scope:"renderJS"}),g.chan.bind("declareMethod",function(a,b){return g[b]=function(){var a=arguments;return new c.Promise(function(c,d){g.chan.call({method:"methodCall",params:[b,Array.prototype.slice.call(a,0)],success:function(a){c(a)},error:function(a){d(a)}})})},"OK"}),g.chan.bind("ready",function(){return k.resolve(g),"OK"}),g.chan.bind("failed",function(a,b){return k.reject(b),"OK"}),c.any([k.promise,c.timeout(5e3)])}function l(){var d,i,j,k,l,s=b.location.href,t=0,u=!1;if(p.hasOwnProperty(s))throw new Error("bootstrap should not be called twice");n=new c.Promise(function(n,v){function w(){var b,e,g=o.parseGadgetHTMLDocument(a);for(e in g)g.hasOwnProperty(e)&&(d.prototype[e]=g[e]);for(d.template_element=a.createElement("div"),i.element=a.body,b=0;b<i.element.childNodes.length;b+=1)d.template_element.appendChild(i.element.childNodes[b].cloneNode(!0));c.all([i.getRequiredJSList(),i.getRequiredCSSList()]).then(function(a){function b(){return i}var e,g,h=a[0],j=a[1];for(e=0;e<h.length;e+=1)q[h[e]]=null;for(e=0;e<j.length;e+=1)r[j[e]]=null;for(m=f,g=new c.Queue,g.push(b),e=0;e<d.ready_list.length;e+=1)g.push(d.ready_list[e]),g.push(b);return g.push(n,function(a){throw v(a),a}),g}).fail(function(a){v(a)})}b.self===b.top?(d=function(){g.call(this)},d.declareMethod=g.declareMethod,d.ready_list=[],d.ready=g.ready,d.prototype=new g,d.prototype.constructor=d,d.prototype.path=s,p[s]=d,i=new p[s]):(j=e.build({window:b.parent,origin:"*",scope:"renderJS"}),d=h,i=new h,j.bind("methodCall",function(a,b){i[b[0]].apply(i,b[1]).then(function(b){a.complete(b)}).fail(function(b){a.error(b.toString())}),a.delayReturn(!0)}),k=function(){0===t&&u===!0&&j.notify({method:"ready"})},l=function(a){t+=1,j.call({method:"declareMethod",params:a,success:function(){t-=1,k()},error:function(){t-=1}})},l("getInterfaceList"),l("getRequiredCSSList"),l("getRequiredJSList"),l("getPath"),l("getTitle"),d.declareMethod=function(a,b){var c=g.declareMethod.apply(this,[a,b]);return l(a),c}),m=d,a.addEventListener("DOMContentLoaded",w,!1)}),b.self!==b.top&&n.then(function(){u=!0,k()}).fail(function(a){throw j.notify({method:"failed",params:a.toString()}),a})}var m,n,o,p={},q={},r={};g.prototype.title="",g.prototype.interface_list=[],g.prototype.path="",g.prototype.html="",g.prototype.required_css_list=[],g.prototype.required_js_list=[],g.ready_list=[],g.ready=function(a){return this.ready_list.push(a),this},g.declareMethod=function(a,b){return this.prototype[a]=function(){var a=this,d=arguments;return(new c.Queue).push(function(){return b.apply(a,d)})},this},g.declareMethod("getInterfaceList",function(){return this.interface_list}).declareMethod("getRequiredCSSList",function(){return this.required_css_list}).declareMethod("getRequiredJSList",function(){return this.required_js_list}).declareMethod("getPath",function(){return this.path}).declareMethod("getTitle",function(){return this.title}).declareMethod("getElement",function(){if(this.element===f)throw new Error("No element defined");return this.element}),h.ready_list=[],h.ready=g.ready,h.prototype=new g,h.prototype.constructor=h,j.ready_list=[],j.ready=g.ready,j.prototype=new g,j.prototype.constructor=j,g.prototype.declareGadget=function(a,b){var d,e=n;return b===f&&(b={}),b.sandbox===f&&(b.sandbox="public"),d=(new c.Queue).push(function(){return e}).push(f,function(){}).push(function(){var c;if("public"===b.sandbox)c=i;else{if("iframe"!==b.sandbox)throw new Error("Unsupported sandbox options '"+b.sandbox+"'");c=k}return c(a,b)}).push(function(a){function b(){return a}var c;for(m=f,c=0;c<a.constructor.ready_list.length;c+=1)d.push(a.constructor.ready_list[c]),d.push(b);return a}).push(f,function(a){throw m=f,a}),n=d},o=function(a){var c;if(a===b?c=m:a instanceof g&&(c=a),c===f)throw new Error("Unknown selector '"+a+"'");return c},o.declareJS=function(b){var d;return d=q.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("script"),e.type="text/javascript",e.src=b,e.onload=function(){q[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareCSS=function(b){var d;return d=r.hasOwnProperty(b)?c.resolve():new c.Promise(function(c,d){var e;e=a.createElement("link"),e.rel="stylesheet",e.type="text/css",e.href=b,e.onload=function(){r[b]=null,c()},e.onerror=function(a){d(a)},a.head.appendChild(e)})},o.declareGadgetKlass=function(a){function b(){var b,c,e;if(!p.hasOwnProperty(a)){b=function(){g.call(this)},b.ready_list=[],b.declareMethod=g.declareMethod,b.ready=g.ready,b.prototype=new g,b.prototype.constructor=b,b.prototype.path=a,b.template_element=(new d).parseFromString(j.responseText,"text/html"),e=o.parseGadgetHTMLDocument(b.template_element);for(c in e)e.hasOwnProperty(c)&&(b.prototype[c]=e[c]);p[a]=b}return p[a]}function e(c,d){function e(){var a;try{0===j.readyState?d(j):4===j.readyState&&(j.status<200||j.status>=300||!/^text\/html[;]?/.test(j.getResponseHeader("Content-Type")||"")?d(j):(a=b(),c(a)))}catch(e){d(e)}}j=new XMLHttpRequest,j.open("GET",a),j.onreadystatechange=e,j.setRequestHeader("Accept","text/html"),j.withCredentials=!0,j.send()}function h(){j!==f&&j.readyState!==j.DONE&&j.abort()}var i,j;return i=p.hasOwnProperty(a)?c.resolve(p[a]):new c.Promise(e,h)},o.clearGadgetKlassList=function(){p={},q={},r={}},o.parseGadgetHTMLDocument=function(a){var b,c,d={title:"",interface_list:[],required_css_list:[],required_js_list:[]};if(9!==a.nodeType)throw new Error("The first parameter should be an HTMLDocument");for(d.title=a.title,b=0;b<a.head.children.length;b+=1)c=a.head.children[b],null!==c.href&&("stylesheet"===c.rel?d.required_css_list.push(c.getAttribute("href")):"text/javascript"===c.type?d.required_js_list.push(c.getAttribute("src")):"http://www.renderjs.org/rel/interface"===c.rel&&d.interface_list.push(c.getAttribute("href")));return d},b.rJS=b.renderJS=o,b.RenderJSGadget=g,b.RenderJSEmbeddedGadget=h,b.RenderJSIframeGadget=j,l()}(document,window,RSVP,DOMParser,Channel);
\ No newline at end of file
{
"name": "renderjs",
"version": "0.3.2",
"version": "0.3.3",
"description": "RenderJs provides HTML5 gadgets",
"main": "dist/renderjs-latest.js",
"directories": {
......
/*! RenderJs v0.3.2 */
/*! RenderJs */
/*
* DOMParser HTML extension
......@@ -311,6 +311,10 @@
.push(function () {
return previous_loading_gadget_promise;
})
.push(undefined, function () {
// Forget previous declareGadget error
return;
})
.push(function () {
var method;
if (options.sandbox === "public") {
......
......@@ -1667,6 +1667,42 @@
});
});
test('One failing gadget does not prevent the others to load', function () {
// Check that dependencies are loaded once if 2 gadgets are created
var gadget = new RenderJSGadget(),
html_url = 'https://example.org/files/qunittest/test12345.html',
html_url2 = 'https://example.org/files/qunittest/test12346.html',
mock;
this.server.respondWith("GET", html_url, [404, {
"Content-Type": "text/html"
}, "error"]);
this.server.respondWith("GET", html_url2, [200, {
"Content-Type": "text/html"
}, "raw html"]);
mock = sinon.mock(renderJS, "parseGadgetHTMLDocument");
mock.expects("parseGadgetHTMLDocument").once().returns({});
stop();
gadget.declareGadget(html_url)
.then(function () {
ok(false);
})
.fail(function () {
return gadget.declareGadget(html_url2);
})
.then(function () {
ok(true);
})
.always(function () {
// Check that only one request has been done.
start();
mock.verify();
mock.restore();
});
});
test('Wait for ready callback before returning', function () {
// Subclass RenderJSGadget to not pollute its namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment