Commit a90c429c authored by Romain Courteaud's avatar Romain Courteaud

Replace aq_dynamic by allowPublicAcquisition.

aq_dynamic was a "low level" method, somehow hard to understand.
Allow acquisition more explicitely by providing the method name allowed.
parent 0f76b594
...@@ -89,20 +89,22 @@ ...@@ -89,20 +89,22 @@
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget.declareAcquiredMethod // RenderJSGadget.declareAcquiredMethod
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function acquire() { function acquire(method_name, argument_list) {
var gadget = this, var gadget = this;
argument_list = arguments;
return new RSVP.Queue() return new RSVP.Queue()
.push(function () { .push(function () {
var aq_dynamic = gadget.aq_dynamic; // Do not specify default __acquired_method_dict on prototype
if (aq_dynamic !== undefined) { // to prevent modifying this default value (with
return aq_dynamic.apply(gadget, argument_list); // allowPublicAcquiredMethod for example)
var aq_dict = gadget.__acquired_method_dict || {};
if (aq_dict.hasOwnProperty(method_name)) {
return aq_dict[method_name].apply(gadget, [argument_list]);
} }
throw new renderJS.AcquisitionError("aq_dynamic is not defined"); throw new renderJS.AcquisitionError("aq_dynamic is not defined");
}) })
.push(undefined, function (error) { .push(undefined, function (error) {
if (error instanceof renderJS.AcquisitionError) { if (error instanceof renderJS.AcquisitionError) {
return gadget.aq_parent.apply(gadget, argument_list); return gadget.aq_parent(method_name, argument_list);
} }
throw error; throw error;
}); });
...@@ -119,6 +121,17 @@ ...@@ -119,6 +121,17 @@
return this; return this;
}; };
/////////////////////////////////////////////////////////////////
// RenderJSGadget.allowPublicAcquiredMethod
/////////////////////////////////////////////////////////////////
RenderJSGadget.allowPublicAcquisition =
function (method_name, callback) {
this.prototype.__acquired_method_dict[method_name] = callback;
// Allow chain
return this;
};
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSEmbeddedGadget // RenderJSEmbeddedGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -529,6 +542,7 @@ ...@@ -529,6 +542,7 @@
tmp_constructor.prototype = new RenderJSGadget(); tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor; tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.__path = url; tmp_constructor.prototype.__path = url;
tmp_constructor.prototype.__acquired_method_dict = {};
// https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest // https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest
// https://developer.mozilla.org/en-US/docs/Web/API/DOMParser // https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
// https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM // https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM
...@@ -795,6 +809,7 @@ ...@@ -795,6 +809,7 @@
}; };
} }
tmp_constructor.prototype.__acquired_method_dict = {};
gadget_loading_klass = tmp_constructor; gadget_loading_klass = tmp_constructor;
function init() { function init() {
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
return ((this.hasOwnProperty("__sub_gadget_dict")) && return ((this.hasOwnProperty("__sub_gadget_dict")) &&
(JSON.stringify(this.__sub_gadget_dict) === "{}")); (JSON.stringify(this.__sub_gadget_dict) === "{}"));
}) })
.declareMethod('isAcquisitionDictInitialize', function () {
return (this.__acquired_method_dict !== undefined);
})
.declareMethod('triggerError', function (value) { .declareMethod('triggerError', function (value) {
throw new Error("Manually triggered embedded error"); throw new Error("Manually triggered embedded error");
}) })
......
/*jslint nomen: true*/ /*jslint nomen: true*/
/*global console */
(function (document, renderJS, QUnit, sinon, URI) { (function (document, renderJS, QUnit, sinon, URI) {
"use strict"; "use strict";
var test = QUnit.test, var test = QUnit.test,
...@@ -452,6 +451,7 @@ ...@@ -452,6 +451,7 @@
var instance; var instance;
equal(Klass.prototype.__path, url); equal(Klass.prototype.__path, url);
deepEqual(Klass.prototype.__acquired_method_dict, {});
equal(Klass.prototype.__foo, 'bar'); equal(Klass.prototype.__foo, 'bar');
equal(Klass.__template_element.nodeType, 9); equal(Klass.__template_element.nodeType, 9);
...@@ -520,6 +520,7 @@ ...@@ -520,6 +520,7 @@
var instance; var instance;
equal(Klass.prototype.__path, url); equal(Klass.prototype.__path, url);
deepEqual(Klass.prototype.__acquired_method_dict, {});
instance = new Klass(); instance = new Klass();
ok(instance instanceof RenderJSGadget); ok(instance instanceof RenderJSGadget);
...@@ -1228,7 +1229,7 @@ ...@@ -1228,7 +1229,7 @@
}); });
test('returns aq_dynamic result if available', function () { test('returns acquired_method result if available', function () {
// Subclass RenderJSGadget to not pollute its namespace // Subclass RenderJSGadget to not pollute its namespace
var Klass = function () { var Klass = function () {
RenderJSGadget.call(this); RenderJSGadget.call(this);
...@@ -1241,19 +1242,20 @@ ...@@ -1241,19 +1242,20 @@
Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod; Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod;
Klass.declareAcquiredMethod("checkIfAqDynamicIsCalled", Klass.declareAcquiredMethod("checkIfAqDynamicIsCalled",
original_method_name); original_method_name);
gadget = new Klass(); Klass.prototype.__acquired_method_dict = {};
Klass.prototype.__acquired_method_dict[original_method_name] =
function (argument_list) {
aq_dynamic_called = true;
equal(this, gadget, "Context should be kept");
deepEqual(argument_list, original_argument_list,
"Argument list should be kept"
);
return "FOO";
};
gadget.aq_dynamic = function (method_name, argument_list) { gadget = new Klass();
aq_dynamic_called = true;
equal(this, gadget, "Context should be kept");
equal(method_name, original_method_name, "Method name should be kept");
deepEqual(argument_list, original_argument_list,
"Argument list should be kept"
);
return "FOO";
};
stop(); stop();
gadget.checkIfAqDynamicIsCalled("foobar", "barfoo") gadget.checkIfAqDynamicIsCalled("foobar", "barfoo")
...@@ -1261,12 +1263,15 @@ ...@@ -1261,12 +1263,15 @@
equal(result, "FOO"); equal(result, "FOO");
equal(aq_dynamic_called, true); equal(aq_dynamic_called, true);
}) })
.fail(function (e) {
ok(false, e);
})
.always(function () { .always(function () {
start(); start();
}); });
}); });
test('fails if aq_dynamic throws an error', function () { test('fails if aquired_method throws an error', function () {
// Subclass RenderJSGadget to not pollute its namespace // Subclass RenderJSGadget to not pollute its namespace
var Klass = function () { var Klass = function () {
RenderJSGadget.call(this); RenderJSGadget.call(this);
...@@ -1274,16 +1279,19 @@ ...@@ -1274,16 +1279,19 @@
original_error = new Error("Custom error for the test"); original_error = new Error("Custom error for the test");
Klass.prototype = new RenderJSGadget(); Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass; Klass.prototype.constructor = Klass;
Klass.prototype.__acquired_method_dict = {};
Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod; Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod;
Klass.declareAcquiredMethod("checkIfAqDynamicThrowsError", Klass.declareAcquiredMethod("checkIfAqDynamicThrowsError",
"foo"); "foo");
gadget = new Klass(); Klass.prototype.__acquired_method_dict = {};
Klass.prototype.__acquired_method_dict.foo =
function () {
throw original_error;
};
gadget.aq_dynamic = function () { gadget = new Klass();
throw original_error;
};
stop(); stop();
gadget.checkIfAqDynamicThrowsError() gadget.checkIfAqDynamicThrowsError()
...@@ -1296,7 +1304,7 @@ ...@@ -1296,7 +1304,7 @@
}); });
}); });
test('returns aq_parent result if aq_dynamic raises AcquisitionError', test('returns aq_parent result if acquired_method raises AcquisitionError',
function () { function () {
// Subclass RenderJSGadget to not pollute its namespace // Subclass RenderJSGadget to not pollute its namespace
var Klass = function () { var Klass = function () {
...@@ -1309,23 +1317,25 @@ ...@@ -1309,23 +1317,25 @@
original_argument_list = ["foobar", "barfoo"]; original_argument_list = ["foobar", "barfoo"];
Klass.prototype = new RenderJSGadget(); Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass; Klass.prototype.constructor = Klass;
Klass.prototype.__acquired_method_dict = {};
Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod; Klass.declareAcquiredMethod = RenderJSGadget.declareAcquiredMethod;
Klass.declareAcquiredMethod("checkIfAqDynamicThrowsAcqError", Klass.declareAcquiredMethod("checkIfAqDynamicThrowsAcqError",
original_method_name); original_method_name);
gadget = new Klass(); Klass.prototype.__acquired_method_dict.foo =
function () {
aq_dynamic_called = true;
equal(i, 0, "aquired_method called first");
i += 1;
throw new renderJS.AcquisitionError("please call aq_parent!");
};
gadget.aq_dynamic = function (method_name, argument_list) { gadget = new Klass();
aq_dynamic_called = true;
equal(i, 0, "aq_dynamic called first");
i += 1;
throw new renderJS.AcquisitionError("please call aq_parent!");
};
gadget.aq_parent = function (method_name, argument_list) { gadget.aq_parent = function (method_name, argument_list) {
aq_parent_called = true; aq_parent_called = true;
equal(i, 1, "aq_parent called after aq_dynamic"); equal(i, 1, "aq_parent called after acquired_method");
equal(this, gadget, "Context should be kept"); equal(this, gadget, "Context should be kept");
equal(method_name, original_method_name, "Method name should be kept"); equal(method_name, original_method_name, "Method name should be kept");
deepEqual(argument_list, original_argument_list, deepEqual(argument_list, original_argument_list,
...@@ -1346,7 +1356,7 @@ ...@@ -1346,7 +1356,7 @@
}); });
}); });
test('returns aq_parent result if aq_dynamic does not exists', test('returns aq_parent result if acquired_method does not exists',
function () { function () {
// Subclass RenderJSGadget to not pollute its namespace // Subclass RenderJSGadget to not pollute its namespace
var Klass = function () { var Klass = function () {
...@@ -1434,8 +1444,10 @@ ...@@ -1434,8 +1444,10 @@
gadget.checkIfAqParentIsUndefined() gadget.checkIfAqParentIsUndefined()
.fail(function (error) { .fail(function (error) {
ok(error instanceof TypeError); ok(error instanceof TypeError);
ok((error.message === "gadget.aq_parent is undefined") || ok((error.message ===
(error.message === "Cannot call method 'apply' of undefined")); "gadget.aq_parent is not a function") ||
(error.message ===
"Object [object Object] has no method 'aq_parent'"), error);
}) })
.always(function () { .always(function () {
start(); start();
...@@ -1443,17 +1455,53 @@ ...@@ -1443,17 +1455,53 @@
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget.aq_dynamic // RenderJSGadgetKlass.allowPublicAcquisition
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
module("RenderJSGadget.aq_dynamic", { module("RenderJSGadgetKlass.allowPublicAcquiredMethod", {
setup: function () { setup: function () {
renderJS.clearGadgetKlassList(); renderJS.clearGadgetKlassList();
} }
}); });
test('aq_dynamic does not exist by default', function () { test('is chainable', function () {
var gadget = new RenderJSGadget(); // Check that allowPublicAcquisition is chainable
equal(gadget.aq_dynamic, undefined);
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
}, result;
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.prototype.__acquired_method_dict = {};
Klass.allowPublicAcquisition = RenderJSGadget.allowPublicAcquisition;
result = Klass.allowPublicAcquisition('testFoo', function () {
return;
});
// allowPublicAcquisition is chainable
equal(result, Klass);
});
test('creates methods on the prototype', function () {
// Check that allowPublicAcquisition create a callable on the prototype
// Subclass RenderJSGadget to not pollute its namespace
var Klass = function () {
RenderJSGadget.call(this);
};
Klass.prototype = new RenderJSGadget();
Klass.prototype.constructor = Klass;
Klass.prototype.__acquired_method_dict = {};
Klass.allowPublicAcquisition = RenderJSGadget.allowPublicAcquisition;
function testFoo() {
return "OK";
}
Klass.allowPublicAcquisition('testFoo', testFoo);
deepEqual(
Klass.prototype.__acquired_method_dict,
{'testFoo': testFoo}
);
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1817,6 +1865,7 @@ ...@@ -1817,6 +1865,7 @@
gadget.declareGadget(url)//, document.getElementById('qunit-fixture')) gadget.declareGadget(url)//, document.getElementById('qunit-fixture'))
.then(function (new_gadget) { .then(function (new_gadget) {
equal(new_gadget.__path, url); equal(new_gadget.__path, url);
deepEqual(new_gadget.__acquired_method_dict, {});
ok(new_gadget instanceof RenderJSGadget); ok(new_gadget instanceof RenderJSGadget);
}) })
.always(function () { .always(function () {
...@@ -2426,6 +2475,7 @@ ...@@ -2426,6 +2475,7 @@
}) })
.then(function (new_gadget) { .then(function (new_gadget) {
equal(new_gadget.__path, absolute_path); equal(new_gadget.__path, absolute_path);
deepEqual(new_gadget.__acquired_method_dict, undefined);
ok(new_gadget instanceof RenderJSIframeGadget); ok(new_gadget instanceof RenderJSIframeGadget);
equal( equal(
new_gadget.__element.innerHTML, new_gadget.__element.innerHTML,
...@@ -2525,6 +2575,14 @@ ...@@ -2525,6 +2575,14 @@
equal(result, true); equal(result, true);
}) })
// acquired_method_dict is created on prototype
.push(function () {
return new_gadget.isAcquisitionDictInitialize();
})
.push(function (result) {
equal(result, true);
})
// acquire check correctly returns result // acquire check correctly returns result
.push(function () { .push(function () {
return new_gadget.callOKAcquire("param1", "param2"); return new_gadget.callOKAcquire("param1", "param2");
...@@ -2685,6 +2743,7 @@ ...@@ -2685,6 +2743,7 @@
.then(function (root_gadget) { .then(function (root_gadget) {
// Check instance // Check instance
equal(root_gadget.__path, window.location.href); equal(root_gadget.__path, window.location.href);
deepEqual(root_gadget.__acquired_method_dict, {});
equal(root_gadget.__title, document.title); equal(root_gadget.__title, document.title);
deepEqual(root_gadget.__interface_list, []); deepEqual(root_gadget.__interface_list, []);
deepEqual(root_gadget.__required_css_list, deepEqual(root_gadget.__required_css_list,
......
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