| Index: tests.html |
| =================================================================== |
| new file mode 100644 |
| --- /dev/null |
| +++ b/tests.html |
| @@ -0,0 +1,173 @@ |
| +<html> |
| +<head> |
| + <meta charset="utf-8"> |
| +</head> |
| +<body> |
| + <script type="text/javascript; version=1.8"> |
| + let exports = {}; |
| + let Cu = { |
| + reportError: function(e) |
| + { |
| + console.error(e); |
| + } |
| + }; |
| + </script> |
| + <script type="text/javascript; version=1.8" src="buildtools/lib/hooks.js"></script> |
| + <script type="text/javascript; version=1.8"> |
| + "use strict"; |
| + |
| + function test(testFunc) |
| + { |
| + let calls = []; |
| + let o = { |
| + "hookable": function(a, b) |
| + { |
| + calls.push(["orig", a, b]); |
| + return "origResult"; |
| + } |
| + }; |
| + |
| + function equals(actual, expected, message) |
| + { |
| + actual = JSON.stringify(actual); |
| + expected = JSON.stringify(expected); |
| + if (actual != expected) |
| + throw new Error(message + " (expected: " + expected + ", actual result:" + actual + ")"); |
| + } |
| + |
| + function checkResult(args, resultExpected, callsExpected) |
| + { |
| + calls.splice(0, calls.length); |
| + let result = o.hookable.apply(o, args); |
| + |
| + equals(result, resultExpected, "Call result"); |
| + equals(calls, callsExpected, "Calls order"); |
| + } |
| + |
| + try |
| + { |
| + testFunc(o, calls, checkResult); |
| + } |
| + catch (e) |
| + { |
| + let pre = document.createElement("pre"); |
| + pre.style.backgroundColor = "#faa"; |
| + pre.textContent = e + "\n" + e.stack; |
| + document.body.appendChild(pre); |
| + } |
| + } |
| + |
| + test((o, calls, checkResult) => |
| + { |
| + checkResult([1, 2], "origResult", [["orig", 1, 2]]); |
| + }); |
| + |
| + // Simple hook |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + }); |
| + checkResult([3, 4], "origResult", [["hook", 3, 4], ["orig", 3, 4]]); |
| + |
| + unhook(); |
| + checkResult([5, 6], "origResult", [["orig", 5, 6]]); |
| + }); |
| + |
| + // Advanced hook: modifying parameters and adding cleanup |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + return [9, 10]; |
| + }, function() |
| + { |
| + calls.push("cleanup"); |
| + }); |
| + checkResult([7, 8], "origResult", [["hook", 7, 8], ["orig", 9, 10], "cleanup"]); |
| + |
| + unhook(); |
| + checkResult([11, 12], "origResult", [["orig", 11, 12]]); |
| + }); |
| + |
| + // Some other extension overriding the hook in a smart way |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + }); |
| + |
| + let origFunc = o.hookable; |
| + o.hookable = function(a, b) |
| + { |
| + calls.push(["override", a, b]); |
| + return origFunc.call(this, a, b); |
| + }; |
| + checkResult([13, 14], "origResult", [["override", 13, 14], ["hook", 13, 14], ["orig", 13, 14]]); |
| + |
| + o.hookable = origFunc; |
| + unhook(); |
| + checkResult([15, 16], "origResult", [["orig", 15, 16]]); |
| + }); |
| + |
| + // Some other extension overriding the hook in a dumb way with toString() |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + }); |
| + |
| + let origFunc = o.hookable; |
| + o.hookable = eval("(" + String(origFunc).replace("{", "{calls.push(['override', a, b]);") + ")"); |
| + checkResult([17, 18], "origResult", [["hook", 17, 18], ["override", 17, 18], ["orig", 17, 18]]); |
| + |
| + // This will currently fail - our hook is removed but other extension's hook stays |
| + o.hookable = origFunc; |
| + unhook(); |
| + checkResult([19, 20], "origResult", [["orig", 19, 20]]); |
| + }); |
| + |
| + // Some other extension overriding the hook in a dumb way with toString() for restoring as well |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + }); |
| + |
| + let origSource = o.hookable.toString(); |
| + o.hookable = eval("(" + origSource.replace("{", "{calls.push(['override', a, b]);") + ")"); |
| + checkResult([21, 22], "origResult", [["hook", 21, 22], ["override", 21, 22], ["orig", 21, 22]]); |
| + |
| + // This will currently fail - our hook is removed but other extension's hook stays |
| + o.hookable = eval("(" + origSource + ")"); |
| + unhook(); |
| + checkResult([23, 24], "origResult", [["orig", 23, 24]]); |
| + }); |
| + |
| + // Some other extension overriding the hook in a dumb way with toSource() |
| + test((o, calls, checkResult) => |
| + { |
| + let unhook = exports.hook(o, "hookable", function(a, b) |
| + { |
| + calls.push(["hook", a, b]); |
| + }); |
| + |
| + let origFunc = o.hookable; |
| + o.hookable = eval(origFunc.toSource().replace("{", "{calls.push(['override', a, b]);")); |
| + checkResult([25, 26], "origResult", [["hook", 25, 26], ["override", 25, 26], ["orig", 25, 26]]); |
| + |
| + // This will currently fail - our hook is removed but other extension's hook stays |
| + o.hookable = origFunc; |
| + unhook(); |
| + checkResult([27, 28], "origResult", [["orig", 27, 28]]); |
| + }); |
| + |
| + alert("All tests done"); |
| + </script> |
| +</body> |
| +</html> |