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> |