Commit 7e1d09df authored by Romain Courteaud's avatar Romain Courteaud

Drop previous implementation.

parent 5f4f924e
......@@ -67,10 +67,10 @@ lib/jio/complex_queries.js:
$(RENDERJS_MIN): $(RENDERJS)
$(UGLIFY_CMD) "$<" > "$@"
${BUILDDIR}/$(RENDERJS).lint: $(RENDERJS) test/renderjs_test2.js
${BUILDDIR}/$(RENDERJS).lint: $(RENDERJS) test/renderjs_test.js
@mkdir -p $(@D)
$(LINT_CMD) "$(RENDERJS)"
$(LINT_CMD) "test/renderjs_test2.js"
$(LINT_CMD) "test/renderjs_test.js"
touch $@
${BUILDDIR}/index.html.ok: test/index.html
......
<html>
<head>
<script data-main="../../require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<div id="say-hello"
data-gadget="say-hello.html"
data-gadget-cacheable="0"
data-gadget-cache-id="say-hello"></div>
</body>
</html>
\ No newline at end of file
<html>
<head></head>
<body>
Hello from the gadget!
</body>
</html>
\ No newline at end of file
<html>
<head>
<script data-main="../../require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<div id="init-gadget"
data-gadget="init-gadget.html"
data-gadget-cacheable="0"
data-gadget-cache-id="init-gadget"
data-gadget-property="{&quot;name&quot;: &quot;Ivan&quot;}"></div>
</body>
</html>
\ No newline at end of file
<html>
<head></head>
<body>
<p>Hello to <span id="name"></span> from the gadget which can be initialized via data-gadget-property attribute from parent gadget!</p>
<script type="text/javascript" language="javascript">
//<![CDATA[
name = RenderJs.GadgetIndex.getGadgetById("init-gadget").name;
$("#name").html(name);
//]]>
</script>
</body>
</html>
\ No newline at end of file
<div>
A (gadget)
<button onclick="RenderJs.GadgetIndex.getGadgetById('A').jsCall1()">A.jsCall1 -> B.jsCall1</button>
<button onclick="$('#A').trigger('htmlEvent1')">HTML event 1</button>
<button onclick="$('#A').trigger('htmlEvent2')">HTML event 2</button>
<button onclick="$('#main-interactor').trigger('htmlEvent3')">
A.htmlEvent3 -> InteractionGadget.htmlEvent3 -> A.htmlEvent3 AND B.htmlEvent3
</button>
<p id="hide" style="display:none;"> hidden text on myownHTMlEvent1</p>
</div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("A");
gadget.jsCall1 = function (){alert("A.jscall1");};
gadget.jsCall2 = function (){alert("A.jscall2");};
gadget.htmlEvent3 = function (){alert("A.htmlEvent3");};
gadget.myOwnHtmlEvent1 = function (){
$("#hide").toggle();
alert("A.myOwnHtmlEvent1");
};
});
//]]>
</script>
\ No newline at end of file
<div>
B (gadget)
<button onclick="RenderJs.GadgetIndex.getGadgetById('B').jsCall2();">B.jsCall2 -> A.jsCall2</button>
</div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("B");
gadget.jsCall1 = function (){alert("B.jscall1");};
gadget.jsCall2 = function (){alert("B.jscall2");};
gadget.htmlEvent1 = function (){alert("B.htmlEvent1");};
gadget.htmlEvent2 = function (){alert("B.htmlEvent2");};
gadget.htmlEvent3 = function (){alert("B.htmlEvent3");};
});
//]]>
</script>
\ No newline at end of file
<html>
<head>
<script data-main="../../require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<div id="A"
data-gadget="A.html"
data-gadget-cacheable="0"
data-gadget-cache-id="A"></div>
<div id="B"
data-gadget="B.html"
data-gadget-cacheable="0"
data-gadget-cache-id="B"></div>
<div data-gadget=""
id="main-interactor"
data-gadget-connection="[
{&quot;source&quot;: &quot;A.jsCall1&quot;, &quot;destination&quot;: &quot;B.jsCall1&quot;},
{&quot;source&quot;: &quot;A.htmlEvent1&quot;, &quot;destination&quot;: &quot;B.htmlEvent1&quot;},
{&quot;source&quot;: &quot;A.htmlEvent1&quot;, &quot;destination&quot;: &quot;A.myOwnHtmlEvent1&quot;},
{&quot;source&quot;: &quot;A.htmlEvent2&quot;, &quot;destination&quot;: &quot;B.htmlEvent2&quot;},
{&quot;source&quot;: &quot;B.jsCall2&quot;, &quot;destination&quot;: &quot;A.jsCall2&quot;},
{&quot;source&quot;: &quot;main-interactor.htmlEvent3&quot;, &quot;destination&quot;: &quot;A.htmlEvent3&quot;},
{&quot;source&quot;: &quot;main-interactor.htmlEvent3&quot;, &quot;destination&quot;: &quot;B.htmlEvent3&quot;}]">
</div>
</body>
</html>
<html>
<head></head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Jquery mobile and RenderJs test</h1>
</div>
<div data-role="content">
<h2>Some documentation for this gadget.</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.0-rc.1/jquery.mobile-1.3.0-rc.1.min.css" />
<link rel="stylesheet" href="jqm-gadget.css" />
<script data-main="require-renderjs_jqm.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Jquery mobile and RenderJs test</h1>
</div>
<div data-role="content">
<div id="jqm-gadget"
data-gadget="jqm-gadget.html"></div>
<div id="jqm-details-gadget"
data-gadget="jqm-details-gadget.html"></div>
<div id="jqm-doc-gadget"
data-gadget="jqm-doc-gadget.html"></div>
</div>
</div>
</body>
</html>
<html>
<head></head>
<body>
Country of origin:<span id="country"> ...</span>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("jqm-details-gadget");
gadget.updateCountry = function (country) {
$("#country").html(country);
};
});
//]]>
</script>
</body>
</html>
<html>
<head></head>
<body>
<ul data-role="listview" data-inset="true" data-filter="false">
<li><a href="documentation.html" class="ui-link-inherit">Link</a></li>
</ul>
</body>
</html>
#jqm-gadget,
#jqm-details-gadget{
width:45%;
float:left;
margin-left:10px;
}
#country{
font-weight: bold;
}
#jqm-doc-gadget{
width:100%;
float:left;
}
\ No newline at end of file
<html>
<head></head>
<body>
<ul data-role="listview" data-inset="true" data-filter="true" id="mylist">
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('Germany');"><a href="#">Audi</a></li>
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('USA');"><a href="#">Cadillac</a></li>
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('Italy');"><a href="#">Ferrari</a></li>
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('Japan');"><a href="#">Toyota</a></li>
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('Russia');"><a href="#">Moskvich</a></li>
<li onclick="RenderJs.GadgetIndex.getGadgetById('jqm-details-gadget').updateCountry('Bulgaria');"><a href="#">Moskvich Aleko</a></li>
</ul>
</body>
</html>
// JavaScript file that is used to load RenderJs depenencies
require.config({
baseUrl: "../..",
paths: {
jqm: "lib/jqm/jquery.mobile-1.3.1.js"
},
});
require([ "require-renderjs", "renderjs", "jqm" ], function(domReady) {
// when all gadgets are loaded make sure JQM renders them
RenderJs.bindReady(
function () {
$("[data-gadget]").trigger('create');
}
);
});
<html>
<head>
<script data-main="require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<p>Contained below gadget will get some JSON data from server and update it on page.</p>
<p>It will also load an additional library (using requirejs) that will be used by this gadget.</p>
<div id="json-gadget"
data-gadget=""
data-gadget-source = "json_file.json"
data-gadget-handler="parseJSONAndUpdateDOM"
data-gadget-cacheable="0"
data-gadget-cache-id="json-gadget">
First name: <div id="first_name"></div>
Last name: <div id="last_name"></div>
</div>
</body>
</html>
\ No newline at end of file
{"first_name": "John",
"last_name": "Doh"}
\ No newline at end of file
function parseJSONAndUpdateDOM(result) {
$("#first_name").text(result['first_name']);
$("#last_name").text(result['last_name']);
}
\ No newline at end of file
// JavaScript file that is used to load RenderJs depenencies
require(["../../lib/jquery/jquery.js",
"../../renderjs.js",
"json_gadget.js"
],
function (domReady) {
// Place code to be executed when libraries are loaded
// impliticly call RenderJs bootstrap
RenderJs.init();
});
<html>
<head>
<script data-main="../../require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<div id="recursive"
data-gadget="recursive.html"
data-gadget-cacheable="0"
data-gadget-cache-id="recursive"></div>
</body>
</html>
\ No newline at end of file
<html>
<head></head>
<body>
<p>
Hello from the recursive contained gadget!
</p>
</body>
</html>
<html>
<head></head>
<body>
<p>
Hello from the recursive gadget!
Below a new gadget will be loaded
</p>
<div data-gadget="recursive-contained.html"
data-gadget-cacheable="0"
data-gadget-cache-id="recursive-contained"></div>
</body>
</html>
\ No newline at end of file
<html>
<head>
<script data-main="../../require-renderjs.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
<head>
<body>
<div id="requirejs-gadget"
data-gadget="requirejs-gadget.html"
data-gadget-cacheable="0"
data-gadget-cache-id="requirejs-gadget"></div>
</body>
</html>
\ No newline at end of file
// This module contains gagdets JavaScript implementation code
function setLoaded() {
$("#loading").text('Loaded now using requirejs.');
}
\ No newline at end of file
// This file defines all required javascript files for this gadget
require(["require-gadget-implementation.js"],
function (domReady) {
// required by this gadget code is loaded so we can use it
setLoaded();
});
<html>
<head>
<script type="text/javascript"
src="require-gadget.js"></script>
</head>
<body>
<p>This gadget uses requirejs to load its dependency.</p>
<div id="loading">Loading ....</div>
</body>
</html>
\ No newline at end of file
.list-item {
text-decoration: none;
display: block;
width: 2em;
}
\ No newline at end of file
<html>
<head>
<link type="text/css" href="gadget-color-picker.css" rel="stylesheet">
</head>
<body>
<h2> Color picker</h2>
<div class="body">
<ul style="list-style: none;">
<li><a href="#/color/0/0/0/" class="list-item" style="background-color:rgb(0,0,0);">&nbsp;</a></li>
<li><a href="#/color/0/0/150/" class="list-item" style="background-color:rgb(0,0,150);">&nbsp;</a></li>
<li><a href="#/color/0/150/0/" class="list-item" style="background-color:rgb(0,150,0);">&nbsp;</a></li>
<li><a href="#/color/0/150/150/" class="list-item" style="background-color:rgb(0,150,150);">&nbsp;</a></li>
<li><a href="#/color/150/0/0/" class="list-item" style="background-color:rgb(150,0,0);">&nbsp;</a></li>
<li><a href="#/color/150/0/150/" class="list-item" style="background-color:rgb(150,0,150);">&nbsp;</a></li>
<li><a href="#/color/150/150/0/" class="list-item" style="background-color:rgb(150,150,0);">&nbsp;</a></li>
<li><a href="#/color/150/150/150/" class="list-item" style="background-color:rgb(150,150,150);">&nbsp;</a></li>
<li style="text-align: center;"><a href="#/color/X/X/X" style="text-decoration: none; display: block; width: 2em;">XXX</a></li>
</ul>
<div class="select-color" style="display: block;"></div>
</div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.getSelfGadget();
gadget.redirect = function () {
// Default route. Redirect to color subapp
$.url.redirect('/color/');
};
gadget.selectColorMessage = function () {
$('.select-color').text("Please select a color");
};
gadget.updateColor = function (red, green, blue) {
$('.select-color').html(
"<div style='background-color:rgb(" + red + "," + green + "," + blue + ");'>&nbsp;<\/div>" +
"<p>Color (" + red + "," + green + "," + blue + ") selected at " + new Date() + "<\/p>");
};
gadget.initRoutes = function () {
// XXX: improve this part so we can declare in RouteGadget
RenderJs.RouteGadget.go($.url.getPath(),
function () {
$('.select-color').html("Unknown color (" + $.url.getPath() + ")");},
2);
};
});
//]]>
</script>
</body>
</html>
<html>
<head></head>
<body>
<h1> This is footer loaded asynchronously at startup</h1>
<div class="route-select">
<ul>
<li><a href="#/footer_gadget_1/">Footer Gadget 1</a></li>
<li><a href="#/footer_gadget_2/">Footer Gadget 2</a></li>
<li><a href="#/footer_gadget_3/">Footer Gadget 3</a></li>
<li><a href="#/footer_gadget_4/">Footer Gadget 4</a></li>
<li><a href="#/footer_gadget_5/">Footer Gadget 5</a></li>
</ul>
</div>
<div id="footer-container">
<div data-gadget-source="" data-gadget-handler="" data-gadget="gadget-three.html" id="footer_gadget_1"></div>
<div data-gadget-source="" data-gadget-handler="" data-gadget="gadget-three.html" id="footer_gadget_2"></div>
<div data-gadget-source="" data-gadget-handler="" data-gadget="gadget-three.html" id="footer_gadget_3"></div>
<div data-gadget-source="" data-gadget-handler="" data-gadget="gadget-three.html" id="footer_gadget_4"></div>
<div data-gadget-source="" data-gadget-handler="" data-gadget="gadget-three.html" id="footer_gadget_5"></div>
<div data-gadget=""
id="footer-router"
data-gadget-route="[
{&quot;source&quot;: &quot;/footer_gadget_1/&quot;, &quot;destination&quot;: &quot;footer_gadget_1.render&quot;},
{&quot;source&quot;: &quot;/footer_gadget_2/&quot;, &quot;destination&quot;: &quot;footer_gadget_2.render&quot;},
{&quot;source&quot;: &quot;/footer_gadget_3/&quot;, &quot;destination&quot;: &quot;footer_gadget_3.render&quot;},
{&quot;source&quot;: &quot;/footer_gadget_4/&quot;, &quot;destination&quot;: &quot;footer_gadget_4.render&quot;},
{&quot;source&quot;: &quot;/footer_gadget_5/&quot;, &quot;destination&quot;: &quot;footer_gadget_5.render&quot;}]">
</div>
</div>
</body>
</html>
<html>
<head></head>
<body>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("gadget-one");
gadget.render = function (){
$("#gadget-one").html("<h2>Gadget 1</h2><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>");
$("#gadget-two").empty(); // XXX: this will become redundant if we use Tabbular gadget
};
});
//]]>
</script>
</body>
</html>
<html>
<head></head>
<body>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.getSelfGadget();
gadget.showMessage = function (msg){
$("#portal-status-message").html(msg);
window.setTimeout(function () {
$("#portal-status-message").empty();
}, 2000);
};
});
//]]>
</script>
</body>
</html>
<html>
<head></head>
<body>
<div class="gadget-id-viewer" style="display:none;">
</div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.getSelfGadget();
$(gadget.getDom()).find(".gadget-id-viewer").html("This is " + gadget.getId())
gadget.render = function (){
gadget = RenderJs.getSelfGadget();
$(gadget.getDom().find(".gadget-id-viewer")).toggle();
};
});
//]]>
</script>
</body>
</html>
<html>
<head></head>
<body>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("gadget-two");
gadget.render = function (){
$("#gadget-one").empty(); // XXX: this will become redundant if we use Tabbular gadget
$("#gadget-two").html("<h2>Gadget 2</h2><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>");
};
});
//]]>
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script data-main="require-renderjs_route.js"
type="text/javascript"
src="../../lib/require/require.js"></script>
</head>
<body>
<div id="portal-status-message"
data-gadget="gadget-portal-status-message.html"></div>
<div data-gadget=""
id="main-router"
data-gadget-route="[
{&quot;source&quot;: &quot;&quot;, &quot;destination&quot;: &quot;gadget-color-picker.redirect&quot;},
{&quot;source&quot;: &quot;/color<path:params>&quot;, &quot;destination&quot;: &quot;gadget-color-picker.initRoutes&quot;},
{&quot;source&quot;: &quot;/color/&quot;,
&quot;destination&quot;: &quot;gadget-color-picker.selectColorMessage&quot;,
&quot;priority&quot;:2},
{&quot;source&quot;: &quot;/color/<int:red>/<int:green>/<int:blue>/&quot;,
&quot;destination&quot;: &quot;gadget-color-picker.updateColor&quot;,
&quot;priority&quot;:2},
{&quot;source&quot;: &quot;/gadget-one/&quot;, &quot;destination&quot;: &quot;main-router.gadget_one&quot;},
{&quot;source&quot;: &quot;/gadget-two/&quot;, &quot;destination&quot;: &quot;main-router.gadget_two&quot;}]">
</div>
<a href="#unknown">Wrong route</a>
<div id="gadget-color-picker"
data-gadget="gadget-color-picker.html"></div>
<a href="#/gadget-one/">Gadget 1</a>&nbsp;
<a href="#/gadget-two/">Gadget 2</a>
<div id="gadget-one"
data-gadget="gadget-one.html"></div>
<div id="gadget-two"
data-gadget="gadget-two.html"></div>
<div id="gadget-footer"
data-gadget="gadget-footer.html"></div>
<div data-gadget=""
id="main-interactor"
data-gadget-connection="[
{&quot;source&quot;: &quot;main-router.gadget_one&quot;, &quot;destination&quot;: &quot;gadget-one.render&quot;},
{&quot;source&quot;: &quot;main-router.gadget_two&quot;, &quot;destination&quot;: &quot;gadget-two.render&quot;}]">
</div>
<noscript>
Please enable Javascript
</noscript>
</body>
</html>
// JavaScript file that is used to load RenderJs depenencies
require.config({
baseUrl: "../..",
paths: {
route: "lib/route/route",
url: "lib/route/url",
jquery: "lib/jquery/jquery",
renderjs: "renderjs",
},
shim: {
url: [ "renderjs" ]
}
});
require([ "renderjs", "require-renderjs", "jquery", "route", "url" ], function(domReady) {
RenderJs.bindReady(function (){
// XXX: try to encapsulate this in router gadget
gadget = RenderJs.GadgetIndex.getGadgetById("main-router");
gadget.gadget_one = function (){
// we use interactionGadget which will call proper gadgets' function
};
gadget.gadget_two = function (){
// we use interactionGadget which will call proper gadgets' function
};
// we have to re-bind (force) interaction gadget as main-route API implemantation changed
RenderJs.InteractionGadget.init(force=1);
$.url.onhashchange(function () {
RenderJs.RouteGadget.go($.url.getPath(),
function () {
// Method to display error to the user
gadget = RenderJs.GadgetIndex.getGadgetById("portal-status-message");
gadget.showMessage(
"<p>Oups, seems the route '<b>" + $.url.getPath() + "<\/b>' doesn't exist!<\/p>" +
"<a href='" + $.url.generateUrl("") + "'>Go back to home<\/a>");
// All routes have been deleted by fail.
// So recreate the default routes using RouteGadget
$("div[data-gadget-route]").each(function (index, element) {
RenderJs.RouteGadget.route($(element));
});
});
});
});
});
......@@ -751,955 +751,3 @@
bootstrap();
}(document, window, jQuery, DOMParser, Channel));
///**
//* By default RenderJs will render all gadgets when page is loaded
//* still it's possible to override this and use explicit gadget rendering.
//*
//* @property RENDERJS_ENABLE_IMPLICIT_GADGET_RENDERING
//* @type {Boolean}
//* @default "true"
//*/
//var RENDERJS_ENABLE_IMPLICIT_GADGET_RENDERING = true;
//
//
///**
//* By default RenderJs will examine and bind all interaction gadgets
//* available.
//*
//* @property RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND
//* @type {Boolean}
//* @default "true"
//*/
//var RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND = true;
//
///**
//* By default RenderJs will examine and create all routes
//*
//* @property RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE
//* @type {Boolean}
//* @default "true"
//*/
//var RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE = true;
//
///**
//Provides the base RenderJs class
//
//@module RenderJs
//**/
//var RenderJs = (function () {
// // a variable indicating if current gadget loading is over or not
// var is_ready = false, current_gadget;
//
// function setSelfGadget(gadget) {
// /*
// * Only used internally to set current gadget being executed.
// */
// current_gadget = gadget;
// }
//
// return {
//
// init: function () {
// /*
// * Do all initialization
// */
// if (RENDERJS_ENABLE_IMPLICIT_GADGET_RENDERING) {
// RenderJs.bootstrap($('body'));
// }
// var root_gadget = RenderJs.GadgetIndex.getRootGadget();
// if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND ||
// RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) {
// // We might have a page without gadgets.
// // Be careful, right now we can be in this case because
// // asynchronous gadget loading is not finished
// if (root_gadget !== undefined) {
// RenderJs.bindReady(
// function () {
// if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND) {
// // examine all Intaction Gadgets and bind accordingly
// RenderJs.InteractionGadget.init();
// }
// if (RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) {
// // create all routes between gadgets
// RenderJs.RouteGadget.init();
// }
// }
// );
// }
// }
// },
//
// bootstrap: function (root) {
// /*
// * Load all gadgets for this DOM element
// * (including recursively contained ones)
// */
// var gadget_id, is_gadget;
// gadget_id = root.attr("id");
// is_gadget = root.attr("data-gadget") !== undefined;
// // this will make RenderJs fire "ready" event when all
// // gadgets are loaded.
// RenderJs.setReady(false);
// if (is_gadget && gadget_id !== undefined) {
// // bootstart root gadget only if it is indeed a gadget
// RenderJs.loadGadget(root);
// }
// RenderJs.loadRecursiveGadget(root);
// },
//
// loadRecursiveGadget: function (root) {
// /*
// * Load all contained gadgets inside passed DOM element.
// */
// var gadget_list, gadget, gadget_id, gadget_js;
// gadget_list = root.find("[data-gadget]");
//
// // register all gadget in advance so checkAndTriggerReady
// // can have accurate information for list of all gadgets
// gadget_list.each(function () {
// gadget = $(this);
// gadget_id = gadget.attr("id");
// gadget_js = new RenderJs.Gadget(gadget_id, gadget);
// RenderJs.GadgetIndex.registerGadget(gadget_js);
// });
//
// // Load chilren
// gadget_list.each(function () {
// RenderJs.loadGadget($(this));
// });
// },
//
// setGadgetAndRecurse: function (gadget, data) {
// /*
// * Set gadget data and recursively load it in case it holds another
// * gadgets.
// */
// // set current gadget as being loaded so gadget instance itself
// // knows which gadget it is
// setSelfGadget(RenderJs.GadgetIndex.getGadgetById(gadget.attr("id")));
// gadget.append(data);
// // reset as no longer current gadget
// setSelfGadget(undefined);
// // a gadget may contain sub gadgets
// RenderJs.loadRecursiveGadget(gadget);
// },
//
// getSelfGadget: function () {
// /*
// * Get current gadget being loaded
// * This function must be used with care as it relies on
// * Javascript nature of being a single threaded application.
// * Currently current gadget is set in a global RenderJs variable
// * before its HTML is inserted into DOM and if multiple threads
// * were running (which is not the case currently)
// * this could lead to reace conditions and unreliable getSelfGadget
// * results.
// * Additionally this function is available only at gadget's script
// * load time - i.e. it can't be used in after that calls.
// * In this case gagdget can save this value internally.
// */
// return current_gadget;
// },
//
// loadGadget: function (gadget) {
// /*
// * Load gadget's SPECs from URL
// */
// var url, gadget_id, gadget_property, cacheable, cache_id,
// i, gadget_index, gadget_index_id,
// app_cache, data, gadget_js, is_update_gadget_data_running;
//
// url = gadget.attr("data-gadget");
// gadget_id = gadget.attr("id");
// gadget_js = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// gadget_index = RenderJs.GadgetIndex.getGadgetList();
//
// if (gadget_js === undefined) {
// // register gadget in javascript namespace
// //if not already registered
// gadget_js = new RenderJs.Gadget(gadget_id, gadget);
// RenderJs.GadgetIndex.registerGadget(gadget_js);
// }
// if (gadget_js.isReady()) {
// // avoid loading again gadget which was loaded before in same page
// return;
// }
//
// // update Gadget's instance with contents of "data-gadget-property"
// gadget_property = gadget.attr("data-gadget-property");
// if (gadget_property !== undefined) {
// gadget_property = $.parseJSON(gadget_property);
// $.each(gadget_property, function (key, value) {
// gadget_js[key] = value;
// });
// }
//
// if (url !== undefined && url !== "") {
// cacheable = gadget.attr("data-gadget-cacheable");
// cache_id = gadget.attr("data-gadget-cache-id");
// if (cacheable !== undefined && cache_id !== undefined) {
// cacheable = Boolean(parseInt(cacheable, 10));
// }
// //cacheable = false ; // to develop faster
// if (cacheable) {
// // get from cache if possible, use last part from URL as
// // cache_key
// app_cache = RenderJs.Cache.get(cache_id, undefined);
// if (app_cache === undefined || app_cache === null) {
// // not in cache so we pull from network and cache
// $.ajax({
// url: url,
// yourCustomData: {
// "gadget_id": gadget_id,
// "cache_id": cache_id
// },
// success: function (data) {
// cache_id = this.yourCustomData.cache_id;
// gadget_id = this.yourCustomData.gadget_id;
// RenderJs.Cache.set(cache_id, data);
// RenderJs.GadgetIndex.getGadgetById(gadget_id).
// setReady();
// RenderJs.setGadgetAndRecurse(gadget, data);
// RenderJs.checkAndTriggerReady();
// RenderJs.updateGadgetData(gadget);
// }
// });
// } else {
// // get from cache
// data = app_cache;
// gadget_js.setReady();
// this.setGadgetAndRecurse(gadget, data);
// this.checkAndTriggerReady();
// RenderJs.updateGadgetData(gadget);
// }
// } else {
// // not to be cached
// $.ajax({
// url: url,
// yourCustomData: {"gadget_id": gadget_id},
// success: function (data) {
// gadget_id = this.yourCustomData.gadget_id;
// RenderJs.GadgetIndex.getGadgetById(gadget_id).
// setReady();
// RenderJs.setGadgetAndRecurse(gadget, data);
// RenderJs.checkAndTriggerReady();
// RenderJs.updateGadgetData(gadget);
// }
// });
// }
// } else {
// // gadget is an inline (InteractorGadget or one using
// // data-gadget-source / data-gadget-handler) so no need
// // to load it from network
// is_update_gadget_data_running = RenderJs.updateGadgetData(gadget);
// if (!is_update_gadget_data_running) {
// // no update is running so gadget is basically ready
// // if update is running then it should take care and set status
// gadget_js.setReady();
// }
// RenderJs.checkAndTriggerReady();
// }
// },
//
// isReady: function () {
// /*
// * Get rendering status
// */
// return is_ready;
// },
//
// setReady: function (value) {
// /*
// * Update rendering status
// */
// is_ready = value;
// },
//
// bindReady: function (ready_function) {
// /*
// * Bind a function on ready gadget loading.
// */
// $("body").one("ready", ready_function);
// },
//
// checkAndTriggerReady: function () {
// /*
// * Trigger "ready" event only if all gadgets were marked as "ready"
// */
// var is_gadget_list_loaded;
// is_gadget_list_loaded = RenderJs.GadgetIndex.isGadgetListLoaded();
// if (is_gadget_list_loaded) {
// if (!RenderJs.isReady()) {
// // backwards compatability with already written code
// RenderJs.GadgetIndex.getRootGadget().getDom().
// trigger("ready");
// // trigger ready on root body element
// $("body").trigger("ready");
// // this set will make sure we fire this event only once
// RenderJs.setReady(true);
// }
// }
// return is_gadget_list_loaded;
// },
//
// updateGadgetData: function (gadget) {
// /*
// * Gadget can be updated from "data-gadget-source" (i.e. a json)
// * and "data-gadget-handler" attributes (i.e. a namespace Javascript)
// */
// var data_source, data_handler;
// data_source = gadget.attr("data-gadget-source");
// data_handler = gadget.attr("data-gadget-handler");
// // acquire data and pass it to method handler
// if (data_source !== undefined && data_source !== "") {
// $.ajax({
// url: data_source,
// dataType: "json",
// yourCustomData: {"data_handler": data_handler,
// "gadget_id": gadget.attr("id")},
// success: function (result) {
// var data_handler, gadget_id;
// data_handler = this.yourCustomData.data_handler;
// gadget_id = this.yourCustomData.gadget_id;
// if (data_handler !== undefined) {
// // eval is not nice to use
// eval(data_handler + "(result)");
// gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// // mark gadget as loaded and fire a check
// // to see if all gadgets are loaded
// gadget.setReady();
// RenderJs.checkAndTriggerReady();
// }
// }
// });
// // asynchronous update happens and respective thread will update
// // status
// return true;
// }
// return false;
// },
//
// addGadget: function (dom_id, gadget_id, gadget, gadget_data_handler,
// gadget_data_source, bootstrap) {
// /*
// * add new gadget and render it
// */
// var html_string, tab_container, tab_gadget;
// tab_container = $('#' + dom_id);
// tab_container.empty();
// html_string = [
// '<div id="' + gadget_id + '"',
// 'data-gadget="' + gadget + '"',
// 'data-gadget-handler="' + gadget_data_handler + '" ',
// 'data-gadget-source="' + gadget_data_source + '"></div>'
// ].join('\n');
//
// tab_container.append(html_string);
// tab_gadget = tab_container.find('#' + gadget_id);
//
// // render new gadget
// if (bootstrap !== false) {
// RenderJs.bootstrap(tab_container);
// }
//
// return tab_gadget;
// },
//
// Cache: (function () {
// /*
// * Generic cache implementation that can fall back to local
// * namespace storage if no "modern" storage like localStorage
// * is available
// */
// return {
// ROOT_CACHE_ID: 'APP_CACHE',
//
// getCacheId: function (cache_id) {
// /*
// * We should have a way to 'purge' localStorage by setting a
// * ROOT_CACHE_ID in all browser instances
// */
// return this.ROOT_CACHE_ID + cache_id;
// },
//
// hasLocalStorage: function () {
// /*
// * Feature test if localStorage is supported
// */
// var mod;
// mod = 'localstorage_test_12345678';
// try {
// localStorage.setItem(mod, mod);
// localStorage.removeItem(mod);
// return true;
// } catch (e) {
// return false;
// }
// },
//
// get: function (cache_id, default_value) {
// /* Get cache key value */
// cache_id = this.getCacheId(cache_id);
// if (this.hasLocalStorage()) {
// return this.LocalStorageCachePlugin.
// get(cache_id, default_value);
// }
// //fallback to javscript namespace cache
// return this.NameSpaceStorageCachePlugin.
// get(cache_id, default_value);
// },
//
// set: function (cache_id, data) {
// /* Set cache key value */
// cache_id = this.getCacheId(cache_id);
// if (this.hasLocalStorage()) {
// this.LocalStorageCachePlugin.set(cache_id, data);
// } else {
// this.NameSpaceStorageCachePlugin.set(cache_id, data);
// }
// },
//
// LocalStorageCachePlugin: (function () {
// /*
// * This plugin saves using HTML5 localStorage.
// */
// return {
// get: function (cache_id, default_value) {
// /* Get cache key value */
// if (localStorage.getItem(cache_id) !== null) {
// return JSON.parse(localStorage.getItem(cache_id));
// }
// return default_value;
// },
//
// set: function (cache_id, data) {
// /* Set cache key value */
// localStorage.setItem(cache_id, JSON.stringify(data));
// }
// };
// }()),
//
// NameSpaceStorageCachePlugin: (function () {
// /*
// * This plugin saves within current page namespace.
// */
// var namespace = {};
//
// return {
// get: function (cache_id, default_value) {
// /* Get cache key value */
// return namespace[cache_id];
// },
//
// set: function (cache_id, data) {
// /* Set cache key value */
// namespace[cache_id] = data;
// }
// };
// }())
// };
// }()),
//
// Gadget: function (gadget_id, dom) {
// /*
// * Javascript Gadget representation
// */
// this.id = gadget_id;
// this.dom = dom;
// this.is_ready = false;
// },
//
// TabbularGadget: (function () {
// /*
// * Generic tabular gadget
// */
// var gadget_list = [];
// return {
// toggleVisibility: function (visible_dom) {
// /*
// * Set tab as active visually and mark as not active rest.
// */
// $(".selected").addClass("not_selected");
// $(".selected").removeClass("selected");
// visible_dom.addClass("selected");
// visible_dom.removeClass("not_selected");
// },
//
// addNewTabGadget: function (dom_id, gadget_id, gadget,
// gadget_data_handler,
// gadget_data_source, bootstrap) {
// /*
// * add new gadget and render it
// */
// var tab_gadget;
// tab_gadget = RenderJs.addGadget(
// dom_id,
// gadget_id,
// gadget,
// gadget_data_handler,
// gadget_data_source,
// bootstrap
// );
//
// // we should unregister all gadgets part of this TabbularGadget
// $.each(gadget_list,
// function (index, gadget_id) {
// var gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// gadget.remove();
// // update list of root gadgets inside TabbularGadget
// gadget_list.splice($.inArray(gadget_id, gadget_list), 1);
// }
// );
// // add it as root gadget
// gadget_list.push(tab_gadget.attr("id"));
// }
// };
// }()),
//
// GadgetIndex: (function () {
// /*
// * Generic gadget index placeholder
// */
// var gadget_list = [];
//
// return {
//
// getGadgetIdListFromDom: function (dom) {
// /*
// * Get list of all gadget's ID from DOM
// */
// var gadget_id_list = [];
// $.each(dom.find('[data-gadget]'),
// function (index, value) {
// gadget_id_list.push($(value).attr("id"));
// }
// );
// return gadget_id_list;
// },
//
// setGadgetList: function (gadget_list_value) {
// /*
// * Set list of registered gadgets
// */
// gadget_list = gadget_list_value;
// },
//
// getGadgetList: function () {
// /*
// * Return list of registered gadgets
// */
// return gadget_list;
// },
//
// registerGadget: function (gadget) {
// /*
// * Register gadget
// */
// if (RenderJs.GadgetIndex.getGadgetById(gadget.id) ===
// undefined) {
// // register only if not already added
// gadget_list.push(gadget);
// }
// },
//
// unregisterGadget: function (gadget) {
// /*
// * Unregister gadget
// */
// var index = $.inArray(gadget, gadget_list);
// if (index !== -1) {
// gadget_list.splice(index, 1);
// }
// },
//
// getGadgetById: function (gadget_id) {
// /*
// * Get gadget javascript representation by its Id
// */
// var gadget;
// gadget = undefined;
// $(RenderJs.GadgetIndex.getGadgetList()).each(
// function (index, value) {
// if (value.getId() === gadget_id) {
// gadget = value;
// }
// }
// );
// return gadget;
// },
//
// getRootGadget: function () {
// /*
// * Return root gadget (always first one in list)
// */
// return this.getGadgetList()[0];
// },
//
// isGadgetListLoaded: function () {
// /*
// * Return True if all gadgets were loaded from network or
// * cache
// */
// var result;
// result = true;
// $(this.getGadgetList()).each(
// function (index, value) {
// if (value.isReady() === false) {
// result = false;
// }
// }
// );
// return result;
// }
// };
// }()),
//
// GadgetCatalog : (function () {
// /*
// * Gadget catalog provides API to get
// * list of gadgets from a repository
// */
// var cache_id = "setGadgetIndexUrlList";
//
// function updateGadgetIndexFromURL(url) {
// // split to base and document url
// var url_list = url.split('/'),
// document_url = url_list[url_list.length - 1],
// d = url_list.splice($.inArray(document_url, url_list), 1),
// base_url = url_list.join('/'),
// web_dav = jIO.newJio({
// "type": "dav",
// "username": "",
// "password": "",
// "url": base_url
// });
// web_dav.get(document_url,
// function (err, response) {
// RenderJs.Cache.set(url, response);
// });
// }
//
// return {
// updateGadgetIndex: function () {
// /*
// * Update gadget index from all configured remote repositories.
// */
// $.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
// function (index, value) {
// updateGadgetIndexFromURL(value);
// });
// },
//
// setGadgetIndexUrlList: function (url_list) {
// /*
// * Set list of Gadget Index repositories.
// */
// // store in Cache (html5 storage)
// RenderJs.Cache.set(cache_id, url_list);
// },
//
// getGadgetIndexUrlList: function () {
// /*
// * Get list of Gadget Index repositories.
// */
// // get from Cache (html5 storage)
// return RenderJs.Cache.get(cache_id, undefined);
// },
//
// getGadgetListThatProvide: function (service) {
// /*
// * Return list of all gadgets that providen a given service.
// * Read this list from data structure created in HTML5 local
// * storage by updateGadgetIndexFromURL
// */
// // get from Cache stored index and itterate over it
// // to find matching ones
// var gadget_list = [];
// $.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
// function (index, url) {
// // get repos from cache
// var cached_repo = RenderJs.Cache.get(url);
// $.each(cached_repo.gadget_list,
// function (index, gadget) {
// if ($.inArray(service, gadget.service_list) > -1) {
// // gadget provides a service, add to list
// gadget_list.push(gadget);
// }
// }
// );
// });
// return gadget_list;
// },
//
// registerServiceList: function (gadget, service_list) {
// /*
// * Register a service provided by a gadget.
// */
// }
// };
// }()),
//
// InteractionGadget : (function () {
// /*
// * Basic gadget interaction gadget implementation.
// */
// return {
//
// init: function (force) {
// /*
// * Inspect DOM and initialize this gadget
// */
// var dom_list, gadget_id;
// if (force === 1) {
// // we explicitly want to re-init elements even if already this
// // is done before
// dom_list = $("div[data-gadget-connection]");
// } else {
// // XXX: improve and save 'bound' on javascript representation
// // of a gadget not DOM
// dom_list = $("div[data-gadget-connection]")
// .filter(function () {
// return $(this).data("bound") !== true;
// })
// .data('bound', true);
// }
// dom_list.each(function (index, element) {
// RenderJs.InteractionGadget.bind($(element));
// });
// },
//
// bind: function (gadget_dom) {
// /*
// * Bind event between gadgets.
// */
// var gadget_id, gadget_connection_list,
// createMethodInteraction = function (
// original_source_method_id,
// source_gadget_id,
// source_method_id,
// destination_gadget_id,
// destination_method_id
// ) {
// var interaction = function () {
// // execute source method
// RenderJs.GadgetIndex.getGadgetById(
// source_gadget_id
// )[original_source_method_id].
// apply(null, arguments);
// // call trigger so bind can be asynchronously called
// RenderJs.GadgetIndex.getGadgetById(
// destination_gadget_id
// ).dom.trigger(source_method_id);
// };
// return interaction;
// },
// createTriggerInteraction = function (
// destination_gadget_id,
// destination_method_id
// ) {
// var interaction = function () {
// RenderJs.GadgetIndex.getGadgetById(
// destination_gadget_id
// )[destination_method_id].
// apply(null, arguments);
// };
// return interaction;
// };
// gadget_id = gadget_dom.attr("id");
// gadget_connection_list =
// gadget_dom.attr("data-gadget-connection");
// gadget_connection_list = $.parseJSON(gadget_connection_list);
// $.each(gadget_connection_list, function (key, value) {
// var source,
// source_gadget_id,
// source_method_id,
// source_gadget,
// destination,
// destination_gadget_id,
// destination_method_id,
// destination_gadget,
// original_source_method_id;
// source = value.source.split(".");
// source_gadget_id = source[0];
// source_method_id = source[1];
// source_gadget = RenderJs.GadgetIndex.
// getGadgetById(source_gadget_id);
//
// destination = value.destination.split(".");
// destination_gadget_id = destination[0];
// destination_method_id = destination[1];
// destination_gadget = RenderJs.GadgetIndex.
// getGadgetById(destination_gadget_id);
//
// if (source_gadget.hasOwnProperty(source_method_id)) {
// // direct javascript use case
// original_source_method_id = "original_" +
// source_method_id;
// source_gadget[original_source_method_id] =
// source_gadget[source_method_id];
// source_gadget[source_method_id] =
// createMethodInteraction(
// original_source_method_id,
// source_gadget_id,
// source_method_id,
// destination_gadget_id,
// destination_method_id
// );
// // we use html custom events for asyncronous method call so
// // bind destination_gadget to respective event
// destination_gadget.dom.bind(
// source_method_id,
// createTriggerInteraction(
// destination_gadget_id,
// destination_method_id
// )
// );
// } else {
// // this is a custom event attached to HTML gadget
// // representation
// source_gadget.dom.bind(
// source_method_id,
// createTriggerInteraction(
// destination_gadget_id,
// destination_method_id
// )
// );
// }
// });
// }
// };
// }()),
//
// RouteGadget : (function () {
// /*
// * A gadget that defines possible routes (i.e. URL changes)
// * between gadgets.
// */
// var route_list = [];
// return {
//
// init: function () {
// /*
// * Inspect DOM and initialize this gadget
// */
// $("div[data-gadget-route]").each(function (index, element) {
// RenderJs.RouteGadget.route($(element));
// });
// },
//
// route: function (gadget_dom) {
// /*
// * Create routes between gadgets.
// */
// var body = $("body"),
// handler_func,
// priority,
// gadget_route_list = gadget_dom.attr("data-gadget-route");
// gadget_route_list = $.parseJSON(gadget_route_list);
// $.each(gadget_route_list, function (key, gadget_route) {
// handler_func = function () {
// var gadget_id = gadget_route.destination.split('.')[0],
// method_id = gadget_route.destination.split('.')[1],
// gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// // set gadget value so getSelfGadget can work
// setSelfGadget(gadget);
// gadget[method_id].apply(null, arguments);
// // reset as no longer needed
// setSelfGadget(undefined);
// };
// // add route itself
// priority = gadget_route.priority;
// if (priority === undefined) {
// // default is 1 -i.e.first level
// priority = 1;
// }
// RenderJs.RouteGadget.add(gadget_route.source,
// handler_func, priority);
// });
// },
//
// add: function (path, handler_func, priority) {
// /*
// * Add a route between path (hashable) and a handler function
// * (part of Gadget's API).
// */
// var body = $("body");
// body
// .route("add", path, 1)
// .done(handler_func);
// // save locally
// route_list.push({"path": path,
// "handler_func": handler_func,
// "priority": priority});
// },
//
// go: function (path, handler_func, priority) {
// /*
// * Go a route.
// */
// var body = $("body");
// body
// .route("go", path, priority)
// .fail(handler_func);
// },
//
// remove: function (path) {
// /*
// * Remove a route.
// */
//
// // XXX: implement remove a route when route.js supports it
// },
//
// getRouteList: function () {
// /*
// * Get list of all router
// */
// return route_list;
// }
// };
// }())
// };
// }());
//
//// Define Gadget prototype
//RenderJs.Gadget.prototype.getId = function () {
// return this.id;
//};
//
//RenderJs.Gadget.prototype.getDom = function () {
// return this.dom;
//};
//
//RenderJs.Gadget.prototype.isReady = function () {
// /*
// * Return True if remote gadget is loaded into DOM.
// */
// return this.is_ready;
//};
//
//RenderJs.Gadget.prototype.setReady = function () {
// /*
// * Return True if remote gadget is loaded into DOM.
// */
// this.is_ready = true;
//};
//
//RenderJs.Gadget.prototype.remove = function () {
// /*
// * Remove gadget (including its DOM element).
// */
// var gadget;
// // unregister root from GadgetIndex
// RenderJs.GadgetIndex.unregisterGadget(this);
// // gadget might contain sub gadgets so before remove entire
// // DOM we must unregister them from GadgetIndex
// this.getDom().find("[data-gadget]").each(function () {
// gadget = RenderJs.GadgetIndex.getGadgetById($(this).attr("id"));
// RenderJs.GadgetIndex.unregisterGadget(gadget);
// });
// // remove root's entire DOM element
// $(this.getDom()).remove();
//};
// JavaScript file that is used to load RenderJs depenencies
require.config({
paths: {
jquery: "lib/jquery/jquery",
"jquery.json": "lib/json/jquery.json.min",
davstorage: "lib/jio/davstorage",
md5: "lib/jio/md5",
jio: "lib/jio/jio",
renderjs: "renderjs"
},
shim: {
"jquery.json": [ "jquery" ],
jio: ["md5"],
davstorage: ["jio"],
renderjs: [ "jquery", "jquery.json", "jio", "md5", "davstorage" ]
}
});
require([ "renderjs" ], function(domReady) {
RenderJs.init();
});
\ No newline at end of file
{
"gadget_list":[ {"title": "HTML WYSIWYG",
"description": "A simple HTML editor",
"url": "http://example.com/html-editor.html",
"service_list": ["edit_html", "view_html"]},
{"title": "SVG WYSIWYG",
"description": "A simple SVG editor",
"url": "http://example.com/svg-editor.html",
"service_list": ["edit_svg", "view_svg"]}
]
}
\ No newline at end of file
......@@ -12,7 +12,7 @@
<script src="../sinon-qunit.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../renderjs.js" type="text/javascript"></script>
<script src="renderjs_test2.js" type="text/javascript"></script>
<script src="renderjs_test.js" type="text/javascript"></script>
</head>
<body>
<h1 id="qunit-header">QUnit renderJS test suite</h1>
......
<div>A (gadget)</div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("A");
gadget.inc = function (){counter = counter +1;};
gadget.inc2 = function (){counter = counter +2;};
});
//]]>
</script>
\ No newline at end of file
<div> B (gadget) </div>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("B");
gadget.inc = function (){counter = counter + 1; };
gadget.htmlEvent1 = function (){counter = counter + 1;};
gadget.inc2 = function (){counter = counter + 2; };
});
//]]>
</script>
\ No newline at end of file
<div id="A"
data-gadget="interactions/A.html"
data-gadget-cacheable="0"
data-gadget-cache-id="A"></div>
<div id="B"
data-gadget="interactions/B.html"
data-gadget-cacheable="0"
data-gadget-cache-id="B"></div>
<div data-gadget=""
id="main-interactor"
data-gadget-connection="[
{&quot;source&quot;: &quot;A.inc&quot;, &quot;destination&quot;: &quot;B.inc&quot;},
{&quot;source&quot;: &quot;A.htmlEvent1&quot;, &quot;destination&quot;: &quot;B.htmlEvent1&quot;},
{&quot;source&quot;: &quot;main-interactor.multiEvent&quot;, &quot;destination&quot;: &quot;A.inc&quot;},
{&quot;source&quot;: &quot;main-interactor.multiEvent&quot;, &quot;destination&quot;: &quot;B.inc&quot;}]"></div>
<div data-gadget=""
id="supplimentary-interactor"
data-gadget-connection="[
{&quot;source&quot;: &quot;A.inc2&quot;, &quot;destination&quot;: &quot;B.inc2&quot;}]"></div>
{"first_name": "John",
"last_name": "Doh"}
\ No newline at end of file
test!!!
\ No newline at end of file
<div id="A"
data-gadget="loading/A.html"></div>
<div id="B"
data-gadget="loading/A.html"></div>
\ No newline at end of file
test!!!
\ No newline at end of file
/*
* RenderJs tests
*/
// in tests we need to call function manually rather than rely
// on implicit calling
RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND=false;
function cleanUp () {
/*
* Clean up namespace between tests
*/
// re-init GadgetIndex
RenderJs.GadgetIndex.setGadgetList([]);
equal(0, RenderJs.GadgetIndex.getGadgetList().length);
}
// used by tests namespace variables
counter = 0;
first_name=''
last_name=''
route_changed=0
function parseJSONAndUpdateNameSpace(result) {
first_name=result['first_name'];
last_name=result['last_name'];
}
function makeid() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
function setupRenderJSTest(){
/*
* Main RenderJS test entry point
*/
module("Cache");
test('Cache', function () {
cache_id = 'my_test';
data = {'gg':1};
RenderJs.Cache.set(cache_id, data);
deepEqual(data, RenderJs.Cache.get(cache_id));
// test return default value if key is missing works
equal("no such key", RenderJs.Cache.get("no_such_key", "no such key"));
});
module("GadgetIndex");
test('GadgetIndex', function () {
cleanUp();
$("#qunit-fixture").append('<div data-gadget="loading/test-gadget.html" id="new">X</div>');
RenderJs.bootstrap($("#qunit-fixture"));
stop();
RenderJs.bindReady(function (){
start();
equal(RenderJs.GadgetIndex.getGadgetList().length, 1);
equal(true, RenderJs.GadgetIndex.isGadgetListLoaded());
equal("new", RenderJs.GadgetIndex.getRootGadget().getDom().attr("id"));
equal(RenderJs.GadgetIndex.getGadgetById("new"), RenderJs.GadgetIndex.getRootGadget());
dom = $("#qunit-fixture");
deepEqual(["new"], RenderJs.GadgetIndex.getGadgetIdListFromDom(dom));
// try register gadget twice and check it's registered once only
RenderJs.GadgetIndex.registerGadget(RenderJs.GadgetIndex.getGadgetById("new"));
// test unregister gadget
equal(RenderJs.GadgetIndex.getGadgetList().length, 1);
equal(RenderJs.GadgetIndex.getGadgetById("new"), RenderJs.GadgetIndex.getRootGadget());
RenderJs.GadgetIndex.unregisterGadget(RenderJs.GadgetIndex.getGadgetById("new"));
equal(RenderJs.GadgetIndex.getGadgetList().length, 0);
/*global window, document, QUnit, jQuery, renderJS, RenderJSGadget */
/*jslint indent: 2, maxerr: 3, maxlen: 79 */
"use strict";
(function (document, $, renderJS, QUnit) {
var test = QUnit.test,
stop = QUnit.stop,
start = QUnit.start,
ok = QUnit.ok,
equal = QUnit.equal,
expect = QUnit.expect,
throws = QUnit.throws,
deepEqual = QUnit.deepEqual;
/////////////////////////////////////////////////////////////////
// parseGadgetHTML
/////////////////////////////////////////////////////////////////
module("renderJS.parseGadgetHTML", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Not valid HTML string', function () {
// Check that parseGadgetHTML returns the default value if the string is
// not a valid xml
deepEqual(renderJS.parseGadgetHTML(""), {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "",
});
});
});
test('Not string', function () {
// Check that parseGadgetHTML throws an error if the parameter is not a
// string
throws(function () {
renderJS.parseGadgetHTML({});
});
});
module("GadgetObject");
test('GadgetObject', function () {
cleanUp();
$("#qunit-fixture").append('<div data-gadget="loading/test-gadget.html" id="new-gadget">X</div>');
RenderJs.bootstrap($("#qunit-fixture"));
stop();
test('Default result value', function () {
// Check default value returned by parseGadgetHTML
deepEqual(renderJS.parseGadgetHTML(""), {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "",
});
});
RenderJs.bindReady(function (){
start();
equal(RenderJs.GadgetIndex.getGadgetList().length, 1);
root_gadget = RenderJs.GadgetIndex.getRootGadget();
equal("new-gadget", root_gadget.getDom().attr("id"));
// test remove gadget
root_gadget.remove();
equal(RenderJs.GadgetIndex.getGadgetList().length, 0);
equal(0, $("#new-gadget").length);
// XXX: test removing a root gadget also removes its sibling gadgets and their DOM
test('Extract title', function () {
// Check that parseGadgetHTML correctly extract the title
var settings,
html = "<html>" +
"<head>" +
"<title>Great title</title>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, 'Great title', 'Title extracted');
});
test('Extract only one title', function () {
// Check that parseGadgetHTML correctly extract the first title
var settings,
html = "<html>" +
"<head>" +
"<title>Great title</title>" +
"<title>Great title 2</title>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, 'Great title', 'First title extracted');
});
test('Extract title only from head', function () {
// Check that parseGadgetHTML only extract title from head
var settings,
html = "<html>" +
"<body>" +
"<title>Great title</title>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, '', 'Title not found');
});
test('Extract body', function () {
// Check that parseGadgetHTML correctly extract the body
var settings,
html = "<html>" +
"<body>" +
"<p>Foo</p>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, "<p>Foo</p>", "HTML extracted");
});
test('Extract all body', function () {
// Check that parseGadgetHTML correctly extracts all bodies
var settings,
html = "<html>" +
"<body>" +
"<p>Foo</p>" +
"</body><body>" +
"<p>Bar</p>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, '<p>Foo</p><p>Bar</p>', 'All bodies extracted');
});
test('Extract body only from html', function () {
// Check that parseGadgetHTML also extract body from head
var settings,
html = "<html>" +
"<head><body><p>Bar</p></body></head>" +
"</html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, "<p>Bar</p>", "Body not found");
});
test('Extract CSS', function () {
// Check that parseGadgetHTML correctly extract the CSS
var settings,
html = "<html>" +
"<head>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list,
['../lib/qunit/qunit.css'],
"CSS extracted");
});
test('Extract CSS order', function () {
// Check that parseGadgetHTML correctly keep CSS order
var settings,
html = "<html>" +
"<head>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"<link rel='stylesheet' href='../lib/qunit/qunit2.css' " +
"type='text/css'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list,
['../lib/qunit/qunit.css', '../lib/qunit/qunit2.css'],
"CSS order kept");
});
test('Extract CSS only from head', function () {
// Check that parseGadgetHTML only extract css from head
var settings,
html = "<html>" +
"<body>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list, [], "CSS not found");
});
test('Extract interface', function () {
// Check that parseGadgetHTML correctly extract the interface
var settings,
html = "<html>" +
"<head>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list,
['./interface/renderable'],
"interface extracted");
});
test('Extract interface order', function () {
// Check that parseGadgetHTML correctly keep interface order
var settings,
html = "<html>" +
"<head>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/field'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list,
['./interface/renderable',
'./interface/field'],
"interface order kept");
});
test('Extract interface only from head', function () {
// Check that parseGadgetHTML only extract interface from head
var settings,
html = "<html>" +
"<body>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list, [], "interface not found");
});
test('Extract JS', function () {
// Check that parseGadgetHTML correctly extract the JS
var settings,
html = "<html>" +
"<head>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list,
['../lib/qunit/qunit.js'],
"JS extracted");
});
test('Extract JS order', function () {
// Check that parseGadgetHTML correctly keep JS order
var settings,
html = "<html>" +
"<head>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"<script src='../lib/qunit/qunit2.js' " +
"type='text/javascript'></script>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list,
['../lib/qunit/qunit.js', '../lib/qunit/qunit2.js'],
"JS order kept");
});
test('Extract JS only from head', function () {
// Check that parseGadgetHTML only extract js from head
var settings,
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list, [], "JS not found");
});
test('Non valid XML (HTML in fact...)', function () {
// Check default value returned by parseGadgetHTML
deepEqual(renderJS.parseGadgetHTML('<!doctype html><html><head>' +
'<title>Test non valid XML</title>' +
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' +
'</head><body><p>Non valid XML</p></body></html>'), {
title: "Test non valid XML",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "<p>Non valid XML</p>",
});
});
});
/////////////////////////////////////////////////////////////////
// declareGadgetKlass
/////////////////////////////////////////////////////////////////
module("renderJS.declareGadgetKlass", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Ajax error reject the promise', function () {
// Check that declareGadgetKlass fails if ajax fails
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test';
server.respondWith("GET", url, [404, {
"Content-Type": "text/html",
}, "foo"]);
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
server.respond();
});
test('Non HTML reject the promise', function () {
// Check that declareGadgetKlass fails if non html is retrieved
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test';
server.respondWith("GET", url, [200, {
"Content-Type": "text/plain",
}, "foo"]);
module("addGadget");
test('addGadget', function () {
cleanUp();
equal(RenderJs.GadgetIndex.getGadgetList().length, 0);
RenderJs.addGadget("qunit-fixture", "new_added", "loading/test-gadget.html", "", "");
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "text/plain should fail");
})
.fail(function (jqXHR, textStatus) {
equal("200", jqXHR.status);
})
.always(function () {
start();
});
server.respond();
});
RenderJs.bindReady(function (){
start();
equal($("#qunit-fixture").children("#new_added").length, 1);
equal(RenderJs.GadgetIndex.getGadgetList().length, 1);
equal(RenderJs.GadgetIndex.getRootGadget().getDom().attr("id"), "new_added");
test('HTML parsing failure reject the promise', function () {
// Check that declareGadgetKlass fails if the html can not be parsed
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, ""]);
mock = this.mock(renderJS, "parseGadgetHTML", function () {
throw new Error();
});
});
mock.expects("parseGadgetHTML").once().throws();
module("TabularGadget");
test('addTabularGadget', function () {
cleanUp();
equal(RenderJs.GadgetIndex.getGadgetList().length, 0);
RenderJs.TabbularGadget.addNewTabGadget("qunit-fixture", "new_added", "loading/test-gadget.html", "", "");
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "text/plain should fail");
})
.fail(function (jqXHR, textStatus) {
equal("200", jqXHR.status);
})
.always(function () {
mock.verify();
start();
});
server.respond();
});
RenderJs.bindReady(function (){
start();
equal($("#qunit-fixture").children("#new_added").length, 1);
equal(RenderJs.GadgetIndex.getGadgetList().length, 1);
equal(RenderJs.GadgetIndex.getRootGadget().getDom().attr("id"), "new_added");
// XXX: test adding a new tab gadget and that old one was removed from
// both DOM and GadgetIndex
});
});
test('Klass creation', function () {
// Check that declareGadgetKlass returns a subclass of RenderJSGadget
// and contains all extracted properties on the prototype
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
module("GadgetInitialization");
test('GadgetInitialization', function () {
cleanUp();
$("#qunit-fixture").append('<div data-gadget="" id="new-init" data-gadget-property="{&quot;name&quot;: &quot;Ivan&quot;, &quot;age&quot;: 33}">X</div>');
RenderJs.bootstrap($("#qunit-fixture"));
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("foo").returns(
{foo: 'bar'}
);
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass) {
var instance;
// test that gadget get a proper initialization from data-gadget-property
equal('Ivan', RenderJs.GadgetIndex.getGadgetById("new-init").name);
equal(33, RenderJs.GadgetIndex.getGadgetById("new-init").age);
equal(Klass.prototype.path, url);
equal(Klass.prototype.foo, 'bar');
instance = new Klass();
ok(instance instanceof RenderJSGadget);
ok(instance instanceof Klass);
ok(Klass !== RenderJSGadget);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
mock.verify();
start();
});
server.respond();
});
test('Klass is not reloaded if called twice', function () {
// Check that declareGadgetKlass does not reload the gadget
// if it has already been loaded
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("foo").returns(
{foo: 'bar'}
);
module("GadgetReadyEvent");
test('GadgetReadyEvent', function () {
cleanUp();
RenderJs.addGadget("qunit-fixture", "new_added", "interactions/index.html", "", "");
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass1) {
renderJS.declareGadgetKlass(url)
.done(function (Klass2) {
equal(Klass1, Klass2);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
mock.verify();
});
// we need to wait for all gadgets loading ...
RenderJs.bindReady(function () {
start();
equal(true, RenderJs.GadgetIndex.isGadgetListLoaded());
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
server.respond();
});
/////////////////////////////////////////////////////////////////
// declareJS
/////////////////////////////////////////////////////////////////
module("renderJS.declareJS", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Download error reject the promise', function () {
// Check that declareJS fails if ajax fails
var url = 'foo://bar';
stop();
renderJS.declareJS(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
});
test('Ajax error reject the promise twice', function () {
// Check that failed declareJS is not cached
var url = 'foo://bar';
stop();
renderJS.declareJS(url)
.always(function () {
renderJS.declareJS(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
});
});
test('Non JS reject the promise', function () {
// Check that declareJS fails if mime type is wrong
var url = "data:image/png;base64," +
window.btoa("= = ="),
previousonerror = window.onerror;
stop();
window.onerror = undefined;
renderJS.declareJS(url)
.done(function (value, textStatus, jqXHR) {
ok(ok, "Non JS mime type should load");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
window.onerror = previousonerror;
start();
});
});
test('JS cleanly loaded', function () {
// Check that declareJS is fetched and loaded
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS fetched and loaded');");
stop();
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS fetched and loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('JS with errors cleanly loaded', function () {
// Check that declareJS is fetched and loaded even if JS contains an error
var url = "data:application/javascript;base64," +
window.btoa("= var var var a a a"),
previousonerror = window.onerror;
stop();
window.onerror = undefined;
renderJS.declareJS(url)
.done(function (aaa) {
ok(true, "JS with error cleanly loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
window.onerror = previousonerror;
start();
});
});
test('JS is not fetched twice', function () {
// Check that declareJS does not load the JS twice
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS not fetched twice');");
stop();
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS not fetched twice");
$("#qunit-fixture").text("");
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
/////////////////////////////////////////////////////////////////
// declareCSS
/////////////////////////////////////////////////////////////////
module("renderJS.declareCSS", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Ajax error resolve the promise', function () {
// Check that declareCSS is resolved if ajax fails
var url = 'foo://bar';
expect(1);
stop();
renderJS.declareCSS(url)
.done(function () {
ok(true, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
ok(false);
})
.always(function () {
start();
});
});
test('Non CSS resolve the promise', function () {
// Check that declareCSS is resolved if mime type is wrong
var url = "data:image/png;base64," +
window.btoa("= = =");
stop();
renderJS.declareCSS(url)
.done(function (value, textStatus, jqXHR) {
ok(true, "Non CSS mime type should load");
})
.fail(function (jqXHR, textStatus) {
ok(false);
})
.always(function () {
start();
});
});
test('CSS cleanly loaded', function () {
// Check that declareCSS is fetched and loaded
var url = "data:text/css;base64," +
window.btoa("#qunit-fixture {background-color: red;}");
stop();
renderJS.declareCSS(url)
.done(function () {
var found = false;
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
found = true;
}
});
ok(found, "CSS in the head");
equal($("#qunit-fixture").css("background-color"), "rgb(255, 0, 0)");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('CSS with errors cleanly loaded', function () {
// Check that declareCSS is fetched and
// loaded even if CSS contains an error
var url = "data:application/javascript;base64," +
window.btoa("throw new Error('foo');");
stop();
renderJS.declareCSS(url)
.done(function () {
ok(true, "CSS with error cleanly loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('CSS is not fetched twice', function () {
// Check that declareCSS does not load the CSS twice
var url = "data:text/css;base64," +
window.btoa("#qunit-fixture {background-color: blue;}");
stop();
renderJS.declareCSS(url)
.done(function () {
equal($("#qunit-fixture").css("background-color"), "rgb(0, 0, 255)");
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
$(style).remove();
}
});
ok($("#qunit-fixture").css("background-color") !== "rgb(0, 0, 255)");
renderJS.declareCSS(url)
.done(function () {
var found = false;
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
found = true;
}
});
ok($("#qunit-fixture").css("background-color") !==
"rgb(0, 0, 255)", $("#qunit-fixture").css("background-color"));
ok(!found);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
/////////////////////////////////////////////////////////////////
// clearGadgetKlassList
/////////////////////////////////////////////////////////////////
module("renderJS.clearGadgetKlassList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('clearGadgetKlassList leads to gadget reload', function () {
// Check that declareGadgetKlass reload the gadget
// after clearGadgetKlassList is called
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").twice().withArgs("foo").returns(
{foo: 'bar'}
);
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass1) {
renderJS.clearGadgetKlassList();
renderJS.declareGadgetKlass(url)
.done(function (Klass2) {
mock.verify();
ok(Klass1 !== Klass2);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
server.respond();
});
test('clearGadgetKlassList leads to JS reload', function () {
// Check that declareJS reload the JS
// after clearGadgetKlassList is called
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS not fetched twice');");
stop();
renderJS.declareJS(url)
.done(function () {
renderJS.clearGadgetKlassList();
equal($("#qunit-fixture").text(), "JS not fetched twice");
$("#qunit-fixture").text("");
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS not fetched twice");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
// test('clearGadgetKlassList leads to CSS reload', function () {
// // Check that declareCSS reload the CSS
// // after clearGadgetKlassList is called
// ok(false, "not implemented");
// });
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getInterfaceList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getInterfaceList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getInterfaceList return a Promise
var gadget = new RenderJSGadget();
gadget.interface_list = "foo";
stop();
gadget.getInterfaceList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getInterfaceList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getInterfaceList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getRequiredCSSList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getRequiredCSSList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getRequiredCSSList return a Promise
var gadget = new RenderJSGadget();
gadget.required_css_list = "foo";
stop();
gadget.getRequiredCSSList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getRequiredCSSList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getRequiredCSSList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getRequiredJSList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getRequiredJSList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getRequiredJSList return a Promise
var gadget = new RenderJSGadget();
gadget.required_js_list = "foo";
stop();
gadget.getRequiredJSList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getRequiredJSList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getRequiredJSList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getPath
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getPath", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns path', function () {
// Check that getPath return a Promise
var gadget = new RenderJSGadget();
gadget.path = "foo";
stop();
gadget.getPath()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getPath return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getPath()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getTitle
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getTitle", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns title', function () {
// Check that getTitle return a Promise
var gadget = new RenderJSGadget();
gadget.title = "foo";
stop();
gadget.getTitle()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getTitle return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getTitle()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getHTML
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getHTML", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns html', function () {
// Check that getHTML return a Promise
var gadget = new RenderJSGadget();
gadget.html = "foo";
stop();
gadget.getHTML()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getHTML return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getHTML()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadgetKlass.declareMethod
/////////////////////////////////////////////////////////////////
module("RenderJSGadgetKlass.declareMethod", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('is chainable', function () {
// Check that declareMethod is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
equal(gadget.testFoo, undefined);
result = Klass.declareMethod('testFoo', function () {
var a;
});
// declareMethod is chainable
equal(result, Klass);
});
test('creates methods on the prototype', function () {
// Check that declareMethod create a callable on the prototype
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, called, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
equal(gadget.testFoo, undefined);
Klass.declareMethod('testFoo', function (value) {
called = value;
});
// Method is added on the instance class prototype
equal(RenderJSGadget.prototype.testFoo, undefined);
ok(gadget.testFoo !== undefined);
ok(Klass.prototype.testFoo !== undefined);
equal(Klass.prototype.testFoo, gadget.testFoo);
// method can be called
gadget.testFoo("Bar");
equal(called, "Bar");
});
test('returns a promise when synchronous function', function () {
// Check that declareMethod returns a promise when defining
// a synchronous function
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
Klass.declareMethod('testFoo', function (value) {
return value;
});
});
module("InteractionGadget");
test('InteractionGadget', function () {
cleanUp();
RenderJs.addGadget("qunit-fixture", "new_add", "interactions/index.html", "", "");
// method can be called
stop();
gadget.testFoo("Bar")
.done(function (param) {
equal(param, "Bar");
})
.fail(function () {
ok(false, "Should not fail when synchronous");
})
.always(function () {
start();
});
});
// we need to wait for all gadgets loading ...
RenderJs.bindReady(function () {
RenderJs.InteractionGadget.init();
test('returns the callback promise if it exists', function () {
// Check that declareMethod returns the promise created by the callback
start();
equal(0, counter);
// A.inc will call B.inc, both will increase counter by 1
RenderJs.GadgetIndex.getGadgetById("A").inc();
equal(2, counter);
// fire pure HTML event on A and test it calls respective B method
$('#A').trigger('htmlEvent1');
equal(3, counter);
// fire pure HTML event that calls multiple destinations methods
// On its side these methods themself can call each other like now
// when A.inc calls B.inc thus result is 6 NOT 5!
$('#main-interactor').trigger('multiEvent');
equal(6, counter);
// check multiple interactors can coexist (a.inc2 +2 -> B.inc2 +2)
RenderJs.GadgetIndex.getGadgetById("A").inc2();
equal(10, counter);
// test force rebind
RenderJs.GadgetIndex.getGadgetById("A").inc2 = function () {return 0;};
equal(0, RenderJs.GadgetIndex.getGadgetById("A").inc2());
// rebind should not override inc2 as already changed
RenderJs.InteractionGadget.init();
equal(0, RenderJs.GadgetIndex.getGadgetById("A").inc2());
// if we force rebind it should be back to previous state
RenderJs.GadgetIndex.getGadgetById("A").inc2 = function (){counter = counter +2;};
RenderJs.InteractionGadget.init(force=1);
RenderJs.GadgetIndex.getGadgetById("A").inc2()
equal(16, counter);
// XXX: test dynamically adding an InteractionGadget
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
Klass.declareMethod('testFoo', function (value) {
var dfr = $.Deferred();
setTimeout(function () {
dfr.reject(value);
});
return dfr.promise();
});
});
module("GadgetDataHandler");
test('GadgetDataHandler', function () {
cleanUp();
$("#qunit-fixture").append('<div data-gadget="" id="json-gadget" data-gadget-source = "json/json_file.json" data-gadget-handler="parseJSONAndUpdateNameSpace"><p>some content</p></div>');
RenderJs.bootstrap($("#qunit-fixture"));
equal('', first_name);
equal('', last_name);
// method can be called
stop();
gadget.testFoo("Bar")
.done(function () {
ok(false, "Callback promise is rejected");
})
.fail(function (param) {
equal(param, "Bar");
})
.always(function () {
start();
});
});
// we need to wait for all gadgets loading ...
RenderJs.bindReady(function () {
start();
equal('John', first_name);
equal('Doh', last_name);
/////////////////////////////////////////////////////////////////
// RenderJSGadgetKlass.ready
/////////////////////////////////////////////////////////////////
module("RenderJSGadgetKlass.ready", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('is chainable', function () {
// Check that ready is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.ready_list = [];
Klass.ready = RenderJSGadget.ready;
gadget = new Klass();
result = Klass.ready(function () {
var a;
});
// ready is chainable
equal(result, Klass);
});
test('store callback in the ready_list property', function () {
// Check that ready is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result,
callback = function () {var a; };
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.ready_list = [];
Klass.ready = RenderJSGadget.ready;
gadget = new Klass();
Klass.ready(callback);
// ready is chainable
deepEqual(Klass.ready_list, [callback]);
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.declareGadget", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns a Promise', function () {
// Check that declareGadget return a Promise
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
module("GadgetCatalog");
test('GadgetCatalog', function () {
cleanUp();
// allow test to be run alone (i.e. url contains arguments)
var base_url = window.location.protocol + "//" + window.location.hostname + window.location.pathname;
// generate random argument to test always with new cache id
var url_list = new Array(base_url + '/gadget_index/gadget_index.json?t='+makeid());
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, html]);
RenderJs.GadgetCatalog.setGadgetIndexUrlList(url_list)
deepEqual(url_list, RenderJs.GadgetCatalog.getGadgetIndexUrlList());
RenderJs.GadgetCatalog.updateGadgetIndex();
stop();
gadget.declareGadget(url, $('#qunit-fixture'))
.always(function () {
ok(true);
start();
});
server.respond();
});
// XXX: until we have a way to know that update which runs asynchronously is over
// we use hard coded timeouts.
setTimeout(function(){
start();
cached = RenderJs.Cache.get(url_list[0]);
equal("HTML WYSIWYG", cached["gadget_list"][0]["title"]);
deepEqual(["edit_html", "view_html"], cached["gadget_list"][0]["service_list"]);
test('provide a gadget instance as callback parameter', function () {
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, html]);
stop();
gadget.declareGadget(url, $('#qunit-fixture'))
.done(function (new_gadget) {
equal(new_gadget.path, url);
})
.always(function () {
start();
});
server.respond();
});
// check that we can find gadgets that provide some service_list
gadget_list = RenderJs.GadgetCatalog.getGadgetListThatProvide("edit_html");
equal("HTML WYSIWYG", gadget_list[0]["title"]);
deepEqual(["edit_html", "view_html"], gadget_list[0]["service_list"]);
gadget_list = RenderJs.GadgetCatalog.getGadgetListThatProvide("view_html");
equal("HTML WYSIWYG", gadget_list[0]["title"]);
deepEqual(["edit_html", "view_html"], gadget_list[0]["service_list"]);
// test('no parameter', function () {
// // Check that missing url reject the declaration
// var gadget = new RenderJSGadget();
// stop();
// gadget.declareGadget()
// .fail(function () {
// ok(true);
// })
// .always(function () {
// start();
// });
// });
gadget_list = RenderJs.GadgetCatalog.getGadgetListThatProvide("edit_svg");
equal("SVG WYSIWYG", gadget_list[0]["title"]);
deepEqual(["edit_svg", "view_svg"], gadget_list[0]["service_list"]);
test('load dependency before returning gadget', function () {
// Check that dependencies are loaded before gadget creation
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = "data:application/javascript;base64," +
window.btoa(
"$('#qunit-fixture').find('div').first().text('youhou');"
),
js2_url = js1_url,
css1_url = "data:text/plain;base64," +
window.btoa(""),
css2_url = css1_url,
html = "<html>" +
"<head>" +
"<title>Foo title</title>" +
"<script src='" + js1_url + "' type='text/javascript'></script>" +
"<script src='" + js2_url + "' type='text/javascript'></script>" +
"<link rel='stylesheet' href='" + css1_url + "' type='text/css'/>" +
"<link rel='stylesheet' href='" + css2_url + "' type='text/css'/>" +
"</head><body><p>Bar content</p></body></html>",
mock,
spy_js,
spy_css;
// no such service is provided by gadget repos
equal(0, RenderJs.GadgetCatalog.getGadgetListThatProvide("edit_html1"));
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, html]);
}, 3000)
spy_js = this.spy(renderJS, "declareJS");
spy_css = this.spy(renderJS, "declareCSS");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs(html).returns({
required_js_list: [js1_url, js2_url],
required_css_list: [css1_url, css2_url],
html: "<p>Bar content</p>",
});
$('#qunit-fixture').html("<div></div><div></div>");
stop();
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div><p>Bar content</p></div>");
ok(spy_js.calledTwice, "JS count " + spy_js.callCount);
equal(spy_js.firstCall.args[0], js1_url, "First JS call");
equal(spy_js.secondCall.args[0], js2_url, "Second JS call");
ok(spy_css.calledTwice, "CSS count " + spy_css.callCount);
equal(spy_css.firstCall.args[0], css1_url, "First CSS call");
equal(spy_css.secondCall.args[0], css2_url, "Second CSS call");
})
.fail(function () {
ok(false);
})
.always(function () {
start();
});
server.respond();
});
module("RouteGadget");
test('RouteGadget', function () {
cleanUp();
RenderJs.addGadget("qunit-fixture", "new_route_add", "route/index.html", "", "");
equal(0, route_changed);
test('Fail if klass can not be loaded', function () {
// Check that gadget is not created if klass is can not be loaded
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test3.html';
server.respondWith("GET", html_url, [404, {
"Content-Type": "text/html",
}, ""]);
stop();
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
ok(false);
})
.fail(function () {
ok(true);
})
.always(function () {
start();
});
server.respond();
});
// we need to wait for all gadgets loading ...
RenderJs.bindReady(function () {
start();
// initialize route gadget as it's loaded asynchronously
RenderJs.RouteGadget.init();
var path_list = [];
$.each(RenderJs.RouteGadget.getRouteList(),
function (index, value) {
path_list.push(value.path);
});
equal(3, RenderJs.RouteGadget.getRouteList().length);
deepEqual(["/gadget-one/", "/gadget-two/","/gadget-three/"], path_list);
// listen to event and do actual routing
$.url.onhashchange(function () {
RenderJs.RouteGadget.go($.url.getPath(),
function () {
console.log("no route");});
});
$.url.go('/gadget-one/');
// give some time so .render finishes, most likely we need some event like .bindReady
// to indicate that respective .render method finishes in generic RenderJs ?
stop();
setTimeout( function () {
// respective gadget .render method must be called and global var changed
equal(1, route_changed);
equal('/gadget-one/', window.location.toString().split('#')[1]);
start();
$.url.go('/gadget-two/');
stop();
setTimeout( function () {
// respective gadget .render method must be called and global var changed
equal(2, route_changed);
equal('/gadget-two/', window.location.toString().split('#')[1]);
start();
$.url.go('/gadget-three/');
stop();
setTimeout( function () {
// respective gadget .render method must be called and global var changed
equal(3, route_changed);
equal('/gadget-three/', window.location.toString().split('#')[1]);
start();
}, 1000);
test('Fail if js can not be loaded', function () {
// Check that dependencies are loaded before gadget creation
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = 'foo://bar2',
mock;
}, 1000);
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
}, 1000);
// XXX: test dynamically adding a RouteGadget
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({
required_js_list: [js1_url]
});
stop();
gadget.declareGadget(html_url, $('#qunit-fixture'))
.done(function (new_gadget) {
ok(false);
})
.fail(function () {
ok(true);
})
.always(function () {
start();
});
server.respond();
});
module("GadgetMultipleInstances");
test('GadgetMultipleInstances', function () {
cleanUp();
$("#qunit-fixture").append('<div data-gadget="self_gadget/self.html" id="self1"</div>');
$("#qunit-fixture").append('<div data-gadget="self_gadget/self.html" id="self2"</div>');
$("#qunit-fixture").append('<div data-gadget="self_gadget/self.html" id="self3"</div>');
RenderJs.bootstrap($("#qunit-fixture"));
test('Do not load gadget dependency twice', function () {
// Check that dependencies are not reloaded if 2 gadgets are created
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = "data:application/javascript;base64," +
window.btoa(
"$('#qunit-fixture').find('div').first().append('youhou');"
),
mock,
spy;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
spy = this.spy($, "ajax");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({
required_js_list: [js1_url]
});
stop();
$('#qunit-fixture').html("<div></div><div></div>");
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.always(function () {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div></div>");
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div></div>");
ok(spy.calledTwice, "Ajax count " + spy.callCount);
equal(spy.firstCall.args[0], html_url, "First ajax call");
deepEqual(spy.secondCall.args[0], {
"cache": true,
"dataType": "script",
"url": js1_url,
}, "Second ajax call");
})
.fail(function () {
ok(false);
})
.always(function () {
start();
});
});
server.respond();
});
// we need to wait for all gadgets loading ...
RenderJs.bindReady(function () {
test('Load 2 concurrent gadgets in parallel', function () {
// Check that dependencies are loaded once if 2 gadgets are created
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
mock,
spy;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
spy = this.spy($, "ajax");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({});
stop();
$.when(
gadget.declareGadget(html_url, $('#qunit-fixture')),
gadget.declareGadget(html_url, $('#qunit-fixture'))
).always(function () {
// Check that only one request has been done.
ok(spy.calledOnce, "Ajax count " + spy.callCount);
equal(spy.firstCall.args[0], html_url, "First ajax call");
start();
// check it's instanciated properly and getSelfGadget returns proper gadget instance
equal("self1", RenderJs.GadgetIndex.getGadgetById("self1").instance_id);
equal("self2", RenderJs.GadgetIndex.getGadgetById("self2").instance_id);
equal("self3", RenderJs.GadgetIndex.getGadgetById("self3").instance_id);
// getSelfGadget works only when gadget is loaded so it must be reset in all other cases
equal(undefined, RenderJs.getSelfGadget());
// only 3 instance should exist
equal(3, RenderJs.GadgetIndex.getGadgetList().length);
});
server.respond();
});
};
}(document, jQuery, renderJS, QUnit));
/*global window, document, QUnit, jQuery, renderJS, RenderJSGadget */
/*jslint indent: 2, maxerr: 3, maxlen: 79 */
"use strict";
(function (document, $, renderJS, QUnit) {
var test = QUnit.test,
stop = QUnit.stop,
start = QUnit.start,
ok = QUnit.ok,
equal = QUnit.equal,
expect = QUnit.expect,
throws = QUnit.throws,
deepEqual = QUnit.deepEqual;
/////////////////////////////////////////////////////////////////
// parseGadgetHTML
/////////////////////////////////////////////////////////////////
module("renderJS.parseGadgetHTML", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Not valid HTML string', function () {
// Check that parseGadgetHTML returns the default value if the string is
// not a valid xml
deepEqual(renderJS.parseGadgetHTML(""), {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "",
});
});
test('Not string', function () {
// Check that parseGadgetHTML throws an error if the parameter is not a
// string
throws(function () {
renderJS.parseGadgetHTML({});
});
});
test('Default result value', function () {
// Check default value returned by parseGadgetHTML
deepEqual(renderJS.parseGadgetHTML(""), {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "",
});
});
test('Extract title', function () {
// Check that parseGadgetHTML correctly extract the title
var settings,
html = "<html>" +
"<head>" +
"<title>Great title</title>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, 'Great title', 'Title extracted');
});
test('Extract only one title', function () {
// Check that parseGadgetHTML correctly extract the first title
var settings,
html = "<html>" +
"<head>" +
"<title>Great title</title>" +
"<title>Great title 2</title>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, 'Great title', 'First title extracted');
});
test('Extract title only from head', function () {
// Check that parseGadgetHTML only extract title from head
var settings,
html = "<html>" +
"<body>" +
"<title>Great title</title>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.title, '', 'Title not found');
});
test('Extract body', function () {
// Check that parseGadgetHTML correctly extract the body
var settings,
html = "<html>" +
"<body>" +
"<p>Foo</p>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, "<p>Foo</p>", "HTML extracted");
});
test('Extract all body', function () {
// Check that parseGadgetHTML correctly extracts all bodies
var settings,
html = "<html>" +
"<body>" +
"<p>Foo</p>" +
"</body><body>" +
"<p>Bar</p>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, '<p>Foo</p><p>Bar</p>', 'All bodies extracted');
});
test('Extract body only from html', function () {
// Check that parseGadgetHTML also extract body from head
var settings,
html = "<html>" +
"<head><body><p>Bar</p></body></head>" +
"</html>";
settings = renderJS.parseGadgetHTML(html);
equal(settings.html, "<p>Bar</p>", "Body not found");
});
test('Extract CSS', function () {
// Check that parseGadgetHTML correctly extract the CSS
var settings,
html = "<html>" +
"<head>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list,
['../lib/qunit/qunit.css'],
"CSS extracted");
});
test('Extract CSS order', function () {
// Check that parseGadgetHTML correctly keep CSS order
var settings,
html = "<html>" +
"<head>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"<link rel='stylesheet' href='../lib/qunit/qunit2.css' " +
"type='text/css'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list,
['../lib/qunit/qunit.css', '../lib/qunit/qunit2.css'],
"CSS order kept");
});
test('Extract CSS only from head', function () {
// Check that parseGadgetHTML only extract css from head
var settings,
html = "<html>" +
"<body>" +
"<link rel='stylesheet' href='../lib/qunit/qunit.css' " +
"type='text/css'/>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_css_list, [], "CSS not found");
});
test('Extract interface', function () {
// Check that parseGadgetHTML correctly extract the interface
var settings,
html = "<html>" +
"<head>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list,
['./interface/renderable'],
"interface extracted");
});
test('Extract interface order', function () {
// Check that parseGadgetHTML correctly keep interface order
var settings,
html = "<html>" +
"<head>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/field'/>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list,
['./interface/renderable',
'./interface/field'],
"interface order kept");
});
test('Extract interface only from head', function () {
// Check that parseGadgetHTML only extract interface from head
var settings,
html = "<html>" +
"<body>" +
"<link rel='http://www.renderjs.org/rel/interface'" +
" href='./interface/renderable'/>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.interface_list, [], "interface not found");
});
test('Extract JS', function () {
// Check that parseGadgetHTML correctly extract the JS
var settings,
html = "<html>" +
"<head>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list,
['../lib/qunit/qunit.js'],
"JS extracted");
});
test('Extract JS order', function () {
// Check that parseGadgetHTML correctly keep JS order
var settings,
html = "<html>" +
"<head>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"<script src='../lib/qunit/qunit2.js' " +
"type='text/javascript'></script>" +
"</head></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list,
['../lib/qunit/qunit.js', '../lib/qunit/qunit2.js'],
"JS order kept");
});
test('Extract JS only from head', function () {
// Check that parseGadgetHTML only extract js from head
var settings,
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
settings = renderJS.parseGadgetHTML(html);
deepEqual(settings.required_js_list, [], "JS not found");
});
test('Non valid XML (HTML in fact...)', function () {
// Check default value returned by parseGadgetHTML
deepEqual(renderJS.parseGadgetHTML('<!doctype html><html><head>' +
'<title>Test non valid XML</title>' +
'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' +
'</head><body><p>Non valid XML</p></body></html>'), {
title: "Test non valid XML",
interface_list: [],
required_css_list: [],
required_js_list: [],
html: "<p>Non valid XML</p>",
});
});
/////////////////////////////////////////////////////////////////
// declareGadgetKlass
/////////////////////////////////////////////////////////////////
module("renderJS.declareGadgetKlass", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Ajax error reject the promise', function () {
// Check that declareGadgetKlass fails if ajax fails
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test';
server.respondWith("GET", url, [404, {
"Content-Type": "text/html",
}, "foo"]);
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
server.respond();
});
test('Non HTML reject the promise', function () {
// Check that declareGadgetKlass fails if non html is retrieved
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test';
server.respondWith("GET", url, [200, {
"Content-Type": "text/plain",
}, "foo"]);
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "text/plain should fail");
})
.fail(function (jqXHR, textStatus) {
equal("200", jqXHR.status);
})
.always(function () {
start();
});
server.respond();
});
test('HTML parsing failure reject the promise', function () {
// Check that declareGadgetKlass fails if the html can not be parsed
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, ""]);
mock = this.mock(renderJS, "parseGadgetHTML", function () {
throw new Error();
});
mock.expects("parseGadgetHTML").once().throws();
stop();
renderJS.declareGadgetKlass(url)
.done(function () {
ok(false, "text/plain should fail");
})
.fail(function (jqXHR, textStatus) {
equal("200", jqXHR.status);
})
.always(function () {
mock.verify();
start();
});
server.respond();
});
test('Klass creation', function () {
// Check that declareGadgetKlass returns a subclass of RenderJSGadget
// and contains all extracted properties on the prototype
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("foo").returns(
{foo: 'bar'}
);
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass) {
var instance;
equal(Klass.prototype.path, url);
equal(Klass.prototype.foo, 'bar');
instance = new Klass();
ok(instance instanceof RenderJSGadget);
ok(instance instanceof Klass);
ok(Klass !== RenderJSGadget);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
mock.verify();
start();
});
server.respond();
});
test('Klass is not reloaded if called twice', function () {
// Check that declareGadgetKlass does not reload the gadget
// if it has already been loaded
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("foo").returns(
{foo: 'bar'}
);
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass1) {
renderJS.declareGadgetKlass(url)
.done(function (Klass2) {
equal(Klass1, Klass2);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
mock.verify();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
server.respond();
});
/////////////////////////////////////////////////////////////////
// declareJS
/////////////////////////////////////////////////////////////////
module("renderJS.declareJS", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Download error reject the promise', function () {
// Check that declareJS fails if ajax fails
var url = 'foo://bar';
stop();
renderJS.declareJS(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
});
test('Ajax error reject the promise twice', function () {
// Check that failed declareJS is not cached
var url = 'foo://bar';
stop();
renderJS.declareJS(url)
.always(function () {
renderJS.declareJS(url)
.done(function () {
ok(false, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
equal("404", jqXHR.status);
})
.always(function () {
start();
});
});
});
test('Non JS reject the promise', function () {
// Check that declareJS fails if mime type is wrong
var url = "data:image/png;base64," +
window.btoa("= = ="),
previousonerror = window.onerror;
stop();
window.onerror = undefined;
renderJS.declareJS(url)
.done(function (value, textStatus, jqXHR) {
ok(ok, "Non JS mime type should load");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
window.onerror = previousonerror;
start();
});
});
test('JS cleanly loaded', function () {
// Check that declareJS is fetched and loaded
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS fetched and loaded');");
stop();
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS fetched and loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('JS with errors cleanly loaded', function () {
// Check that declareJS is fetched and loaded even if JS contains an error
var url = "data:application/javascript;base64," +
window.btoa("= var var var a a a"),
previousonerror = window.onerror;
stop();
window.onerror = undefined;
renderJS.declareJS(url)
.done(function (aaa) {
ok(true, "JS with error cleanly loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
window.onerror = previousonerror;
start();
});
});
test('JS is not fetched twice', function () {
// Check that declareJS does not load the JS twice
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS not fetched twice');");
stop();
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS not fetched twice");
$("#qunit-fixture").text("");
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
/////////////////////////////////////////////////////////////////
// declareCSS
/////////////////////////////////////////////////////////////////
module("renderJS.declareCSS", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('Ajax error resolve the promise', function () {
// Check that declareCSS is resolved if ajax fails
var url = 'foo://bar';
expect(1);
stop();
renderJS.declareCSS(url)
.done(function () {
ok(true, "404 should fail");
})
.fail(function (jqXHR, textStatus) {
ok(false);
})
.always(function () {
start();
});
});
test('Non CSS resolve the promise', function () {
// Check that declareCSS is resolved if mime type is wrong
var url = "data:image/png;base64," +
window.btoa("= = =");
stop();
renderJS.declareCSS(url)
.done(function (value, textStatus, jqXHR) {
ok(true, "Non CSS mime type should load");
})
.fail(function (jqXHR, textStatus) {
ok(false);
})
.always(function () {
start();
});
});
test('CSS cleanly loaded', function () {
// Check that declareCSS is fetched and loaded
var url = "data:text/css;base64," +
window.btoa("#qunit-fixture {background-color: red;}");
stop();
renderJS.declareCSS(url)
.done(function () {
var found = false;
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
found = true;
}
});
ok(found, "CSS in the head");
equal($("#qunit-fixture").css("background-color"), "rgb(255, 0, 0)");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('CSS with errors cleanly loaded', function () {
// Check that declareCSS is fetched and
// loaded even if CSS contains an error
var url = "data:application/javascript;base64," +
window.btoa("throw new Error('foo');");
stop();
renderJS.declareCSS(url)
.done(function () {
ok(true, "CSS with error cleanly loaded");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
});
test('CSS is not fetched twice', function () {
// Check that declareCSS does not load the CSS twice
var url = "data:text/css;base64," +
window.btoa("#qunit-fixture {background-color: blue;}");
stop();
renderJS.declareCSS(url)
.done(function () {
equal($("#qunit-fixture").css("background-color"), "rgb(0, 0, 255)");
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
$(style).remove();
}
});
ok($("#qunit-fixture").css("background-color") !== "rgb(0, 0, 255)");
renderJS.declareCSS(url)
.done(function () {
var found = false;
$('head').find('link[rel=stylesheet]').each(function (i, style) {
if (style.href === url) {
found = true;
}
});
ok($("#qunit-fixture").css("background-color") !==
"rgb(0, 0, 255)", $("#qunit-fixture").css("background-color"));
ok(!found);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
/////////////////////////////////////////////////////////////////
// clearGadgetKlassList
/////////////////////////////////////////////////////////////////
module("renderJS.clearGadgetKlassList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('clearGadgetKlassList leads to gadget reload', function () {
// Check that declareGadgetKlass reload the gadget
// after clearGadgetKlassList is called
var server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
mock;
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, "foo"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").twice().withArgs("foo").returns(
{foo: 'bar'}
);
stop();
renderJS.declareGadgetKlass(url)
.done(function (Klass1) {
renderJS.clearGadgetKlassList();
renderJS.declareGadgetKlass(url)
.done(function (Klass2) {
mock.verify();
ok(Klass1 !== Klass2);
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
server.respond();
});
test('clearGadgetKlassList leads to JS reload', function () {
// Check that declareJS reload the JS
// after clearGadgetKlassList is called
var url = "data:application/javascript;base64," +
window.btoa("$('#qunit-fixture').text('JS not fetched twice');");
stop();
renderJS.declareJS(url)
.done(function () {
renderJS.clearGadgetKlassList();
equal($("#qunit-fixture").text(), "JS not fetched twice");
$("#qunit-fixture").text("");
renderJS.declareJS(url)
.done(function () {
equal($("#qunit-fixture").text(), "JS not fetched twice");
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
})
.always(function () {
start();
});
})
.fail(function (jqXHR, textStatus) {
ok(false, "Failed to load " + textStatus + " " + jqXHR.status);
start();
});
});
// test('clearGadgetKlassList leads to CSS reload', function () {
// // Check that declareCSS reload the CSS
// // after clearGadgetKlassList is called
// ok(false, "not implemented");
// });
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getInterfaceList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getInterfaceList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getInterfaceList return a Promise
var gadget = new RenderJSGadget();
gadget.interface_list = "foo";
stop();
gadget.getInterfaceList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getInterfaceList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getInterfaceList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getRequiredCSSList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getRequiredCSSList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getRequiredCSSList return a Promise
var gadget = new RenderJSGadget();
gadget.required_css_list = "foo";
stop();
gadget.getRequiredCSSList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getRequiredCSSList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getRequiredCSSList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getRequiredJSList
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getRequiredJSList", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns interface_list', function () {
// Check that getRequiredJSList return a Promise
var gadget = new RenderJSGadget();
gadget.required_js_list = "foo";
stop();
gadget.getRequiredJSList()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getRequiredJSList return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getRequiredJSList()
.done(function (result) {
deepEqual(result, []);
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getPath
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getPath", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns path', function () {
// Check that getPath return a Promise
var gadget = new RenderJSGadget();
gadget.path = "foo";
stop();
gadget.getPath()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getPath return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getPath()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getTitle
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getTitle", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns title', function () {
// Check that getTitle return a Promise
var gadget = new RenderJSGadget();
gadget.title = "foo";
stop();
gadget.getTitle()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getTitle return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getTitle()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getHTML
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getHTML", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns html', function () {
// Check that getHTML return a Promise
var gadget = new RenderJSGadget();
gadget.html = "foo";
stop();
gadget.getHTML()
.done(function (result) {
equal(result, "foo");
})
.always(function () {
start();
});
});
test('default value', function () {
// Check that getHTML return a Promise
var gadget = new RenderJSGadget();
stop();
gadget.getHTML()
.done(function (result) {
equal(result, "");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadgetKlass.declareMethod
/////////////////////////////////////////////////////////////////
module("RenderJSGadgetKlass.declareMethod", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('is chainable', function () {
// Check that declareMethod is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
equal(gadget.testFoo, undefined);
result = Klass.declareMethod('testFoo', function () {
var a;
});
// declareMethod is chainable
equal(result, Klass);
});
test('creates methods on the prototype', function () {
// Check that declareMethod create a callable on the prototype
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, called, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
equal(gadget.testFoo, undefined);
Klass.declareMethod('testFoo', function (value) {
called = value;
});
// Method is added on the instance class prototype
equal(RenderJSGadget.prototype.testFoo, undefined);
ok(gadget.testFoo !== undefined);
ok(Klass.prototype.testFoo !== undefined);
equal(Klass.prototype.testFoo, gadget.testFoo);
// method can be called
gadget.testFoo("Bar");
equal(called, "Bar");
});
test('returns a promise when synchronous function', function () {
// Check that declareMethod returns a promise when defining
// a synchronous function
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
Klass.declareMethod('testFoo', function (value) {
return value;
});
// method can be called
stop();
gadget.testFoo("Bar")
.done(function (param) {
equal(param, "Bar");
})
.fail(function () {
ok(false, "Should not fail when synchronous");
})
.always(function () {
start();
});
});
test('returns the callback promise if it exists', function () {
// Check that declareMethod returns the promise created by the callback
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.declareMethod = RenderJSGadget.declareMethod;
gadget = new Klass();
Klass.declareMethod('testFoo', function (value) {
var dfr = $.Deferred();
setTimeout(function () {
dfr.reject(value);
});
return dfr.promise();
});
// method can be called
stop();
gadget.testFoo("Bar")
.done(function () {
ok(false, "Callback promise is rejected");
})
.fail(function (param) {
equal(param, "Bar");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadgetKlass.ready
/////////////////////////////////////////////////////////////////
module("RenderJSGadgetKlass.ready", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('is chainable', function () {
// Check that ready is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.ready_list = [];
Klass.ready = RenderJSGadget.ready;
gadget = new Klass();
result = Klass.ready(function () {
var a;
});
// ready is chainable
equal(result, Klass);
});
test('store callback in the ready_list property', function () {
// Check that ready is chainable
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, gadget, result,
callback = function () {var a; };
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.ready_list = [];
Klass.ready = RenderJSGadget.ready;
gadget = new Klass();
Klass.ready(callback);
// ready is chainable
deepEqual(Klass.ready_list, [callback]);
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.declareGadget", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns a Promise', function () {
// Check that declareGadget return a Promise
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, html]);
stop();
gadget.declareGadget(url, $('#qunit-fixture'))
.always(function () {
ok(true);
start();
});
server.respond();
});
test('provide a gadget instance as callback parameter', function () {
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
url = 'https://example.org/files/qunittest/test',
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
server.respondWith("GET", url, [200, {
"Content-Type": "text/html",
}, html]);
stop();
gadget.declareGadget(url, $('#qunit-fixture'))
.done(function (new_gadget) {
equal(new_gadget.path, url);
})
.always(function () {
start();
});
server.respond();
});
// test('no parameter', function () {
// // Check that missing url reject the declaration
// var gadget = new RenderJSGadget();
// stop();
// gadget.declareGadget()
// .fail(function () {
// ok(true);
// })
// .always(function () {
// start();
// });
// });
test('load dependency before returning gadget', function () {
// Check that dependencies are loaded before gadget creation
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = "data:application/javascript;base64," +
window.btoa(
"$('#qunit-fixture').find('div').first().text('youhou');"
),
js2_url = js1_url,
css1_url = "data:text/plain;base64," +
window.btoa(""),
css2_url = css1_url,
html = "<html>" +
"<head>" +
"<title>Foo title</title>" +
"<script src='" + js1_url + "' type='text/javascript'></script>" +
"<script src='" + js2_url + "' type='text/javascript'></script>" +
"<link rel='stylesheet' href='" + css1_url + "' type='text/css'/>" +
"<link rel='stylesheet' href='" + css2_url + "' type='text/css'/>" +
"</head><body><p>Bar content</p></body></html>",
mock,
spy_js,
spy_css;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, html]);
spy_js = this.spy(renderJS, "declareJS");
spy_css = this.spy(renderJS, "declareCSS");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs(html).returns({
required_js_list: [js1_url, js2_url],
required_css_list: [css1_url, css2_url],
html: "<p>Bar content</p>",
});
$('#qunit-fixture').html("<div></div><div></div>");
stop();
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div><p>Bar content</p></div>");
ok(spy_js.calledTwice, "JS count " + spy_js.callCount);
equal(spy_js.firstCall.args[0], js1_url, "First JS call");
equal(spy_js.secondCall.args[0], js2_url, "Second JS call");
ok(spy_css.calledTwice, "CSS count " + spy_css.callCount);
equal(spy_css.firstCall.args[0], css1_url, "First CSS call");
equal(spy_css.secondCall.args[0], css2_url, "Second CSS call");
})
.fail(function () {
ok(false);
})
.always(function () {
start();
});
server.respond();
});
test('Fail if klass can not be loaded', function () {
// Check that gadget is not created if klass is can not be loaded
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test3.html';
server.respondWith("GET", html_url, [404, {
"Content-Type": "text/html",
}, ""]);
stop();
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
ok(false);
})
.fail(function () {
ok(true);
})
.always(function () {
start();
});
server.respond();
});
test('Fail if js can not be loaded', function () {
// Check that dependencies are loaded before gadget creation
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = 'foo://bar2',
mock;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({
required_js_list: [js1_url]
});
stop();
gadget.declareGadget(html_url, $('#qunit-fixture'))
.done(function (new_gadget) {
ok(false);
})
.fail(function () {
ok(true);
})
.always(function () {
start();
});
server.respond();
});
test('Do not load gadget dependency twice', function () {
// Check that dependencies are not reloaded if 2 gadgets are created
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
js1_url = "data:application/javascript;base64," +
window.btoa(
"$('#qunit-fixture').find('div').first().append('youhou');"
),
mock,
spy;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
spy = this.spy($, "ajax");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({
required_js_list: [js1_url]
});
stop();
$('#qunit-fixture').html("<div></div><div></div>");
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.always(function () {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div></div>");
gadget.declareGadget(html_url, $('#qunit-fixture').find("div").last())
.done(function (new_gadget) {
equal($('#qunit-fixture').html(),
"<div>youhou</div><div></div>");
ok(spy.calledTwice, "Ajax count " + spy.callCount);
equal(spy.firstCall.args[0], html_url, "First ajax call");
deepEqual(spy.secondCall.args[0], {
"cache": true,
"dataType": "script",
"url": js1_url,
}, "Second ajax call");
})
.fail(function () {
ok(false);
})
.always(function () {
start();
});
});
server.respond();
});
test('Load 2 concurrent gadgets in parallel', function () {
// Check that dependencies are loaded once if 2 gadgets are created
var gadget = new RenderJSGadget(),
server = this.sandbox.useFakeServer(),
html_url = 'https://example.org/files/qunittest/test2.html',
mock,
spy;
server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html",
}, "raw html"]);
spy = this.spy($, "ajax");
mock = this.mock(renderJS, "parseGadgetHTML");
mock.expects("parseGadgetHTML").once().withArgs("raw html").returns({});
stop();
$.when(
gadget.declareGadget(html_url, $('#qunit-fixture')),
gadget.declareGadget(html_url, $('#qunit-fixture'))
).always(function () {
// Check that only one request has been done.
ok(spy.calledOnce, "Ajax count " + spy.callCount);
equal(spy.firstCall.args[0], html_url, "First ajax call");
start();
});
server.respond();
});
}(document, jQuery, renderJS, QUnit));
// JavaScript file that is used to load RenderJs depenencies
require.config({
baseUrl: "..",
paths: {
route: "lib/route/route",
url: "lib/route/url",
jquery: "lib/jquery/jquery",
renderjs: "renderjs",
},
shim: {
"test/renderjs_test": [ "renderjs" ],
"url": ["renderjs"],
"route": ["url"]
}
});
require([ "require-renderjs", "test/renderjs_test", "url", "route" ], function(domReady) {
setupRenderJSTest();
});
<html>
<head></head>
<body>
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.GadgetIndex.getGadgetById("gadget-one");
gadget.gadget_one = function () {
route_changed=1; // so we can test this method was actually called from qunit
};
gadget.gadget_two = function () {
route_changed=2; // so we can test this method was actually called from qunit
};
gadget.gadget_three = function () {
route_changed=3; // so we can test this method was actually called from qunit
};
});
//]]>
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<div data-gadget=""
id="main-router"
data-gadget-route="[
{&quot;source&quot;: &quot;/gadget-one/&quot;, &quot;destination&quot;: &quot;gadget-one.gadget_one&quot;},
{&quot;source&quot;: &quot;/gadget-two/&quot;, &quot;destination&quot;: &quot;gadget-one.gadget_two&quot;}]">
</div>
<div data-gadget=""
id="suplimentary-router"
data-gadget-route="[
{&quot;source&quot;: &quot;/gadget-three/&quot;, &quot;destination&quot;: &quot;gadget-one.gadget_three&quot;}]">
</div>
<div id="gadget-one"
data-gadget="route/gadget-one.html"></div>
</body>
</html>
\ No newline at end of file
<script type="text/javascript" language="javascript">
//<![CDATA[
$(document).ready(function() {
gadget = RenderJs.getSelfGadget();
gadget.instance_id = gadget.getId();
});
//]]>
</script>
\ No newline at end of file
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