UNPKG

tiddlywiki

Version:
220 lines (196 loc) 7.11 kB
/*\ title: test-widget-event.js type: application/javascript tags: [[$:/tags/test-spec]] \*/ "use strict"; describe("Widget Event Listeners", function() { var widget = require("$:/core/modules/widgets/widget.js"); function createWidgetNode(parseTreeNode,wiki,parentWidget) { return new widget.widget(parseTreeNode,{ wiki: wiki, document: $tw.fakeDocument, parentWidget: parentWidget }); } it("should call all added event listeners on dispatchEvent", function() { var calls = []; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); // Add a function listener. widget.addEventListener("testEvent", function(e) { calls.push("funcListener"); return true; }); // Setup a method on widget for string listener. widget.testHandler = function(e) { calls.push("methodListener"); return true; }; widget.addEventListener("testEvent", "testHandler"); var event = {type:"testEvent"}; var result = widget.dispatchEvent(event); expect(result).toBe(true); expect(calls.length).toBe(2); expect(calls).toContain("funcListener"); expect(calls).toContain("methodListener"); }); it("should remove an event listener correctly", function() { var calls = []; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); function listener(e) { calls.push("listener"); return true; } // Add listener twice: once as function and then add another distinct listener. widget.addEventListener("removeTest", listener); widget.addEventListener("removeTest", function(e) { calls.push("secondListener"); return true; }); // Remove the function listener. widget.removeEventListener("removeTest", listener); var event = {type:"removeTest"}; var result = widget.dispatchEvent(event); expect(result).toBe(true); expect(calls.length).toBe(1); expect(calls).toContain("secondListener"); expect(calls).not.toContain("listener"); }); it("stop further propagation by returns false won't block other listeners on the same level.", function() { var calls = []; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); widget.addEventListener("stopEvent", function(e) { calls.push("first"); // stops further propagation, but still dispatch event for second listener. return false; }); widget.addEventListener("stopEvent", function(e) { calls.push("second"); return true; }); var event = {type:"stopEvent"}; var result = widget.dispatchEvent(event); expect(result).toBe(false); expect(calls.length).toBe(2); expect(calls).toContain("first"); expect(calls).toContain("second"); }); it("should dispatch event to parent widget if not handled on child", function() { var parentCalls = []; var wiki = $tw.test.wiki(); var parentWidget = createWidgetNode({type:"widget", text:"text"}, wiki); parentWidget.addEventListener("parentEvent", function(e) { parentCalls.push("parentListener"); return true; }); // Create a child with parentWidget assigned. var childWidget = createWidgetNode({type:"widget", text:"text"}, wiki, parentWidget); // No listener on child; so dispatch should bubble up. var event = {type:"parentEvent"}; var result = childWidget.dispatchEvent(event); expect(result).toBe(true); expect(parentCalls.length).toBe(1); expect(parentCalls).toContain("parentListener"); }); it("should not dispatch event to parent if child's listener stops propagation", function() { var parentCalls = []; var wiki = $tw.test.wiki(); var parentWidget = createWidgetNode({type:"widget", text:"text"}, wiki); parentWidget.addEventListener("bubbleTest", function(e) { parentCalls.push("parentListener"); return true; }); var childWidget = createWidgetNode({type:"widget", text:"text"}, wiki, parentWidget); childWidget.addEventListener("bubbleTest", function(e) { return false; // Stop event propagation }); var event = {type:"bubbleTest"}; var result = childWidget.dispatchEvent(event); expect(result).toBe(false); expect(parentCalls.length).toBe(0); }); it("should call multiple listeners in proper order across child and parent", function() { var calls = []; var wiki = $tw.test.wiki(); var parentWidget = createWidgetNode({type:"widget", text:"text"}, wiki); parentWidget.addEventListener("chainEvent", function(e) { calls.push("parentListener"); return true; }); var childWidget = createWidgetNode({type:"widget", text:"text"}, wiki, parentWidget); childWidget.addEventListener("chainEvent", function(e) { calls.push("childListener"); return true; }); var event = {type:"chainEvent"}; var result = childWidget.dispatchEvent(event); expect(result).toBe(true); expect(calls.length).toBe(2); // First call from child widget and then parent's listener. expect(calls[0]).toBe("childListener"); expect(calls[1]).toBe("parentListener"); }); // Additional tests for multiple event types it("should handle events of different types separately", function() { var callsA = []; var callsB = []; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); widget.addEventListener("eventA", function(e) { callsA.push("A1"); return true; }); widget.addEventListener("eventB", function(e) { callsB.push("B1"); return true; }); widget.dispatchEvent({type:"eventA"}); widget.dispatchEvent({type:"eventB"}); expect(callsA).toContain("A1"); expect(callsB).toContain("B1"); }); // Test using $tw.utils.each in removeEventListener internally (behavior verified via dispatch) it("should remove listeners using $tw.utils.each without affecting other listeners", function() { var calls = []; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); function listener1(e) { calls.push("listener1"); return true; } function listener2(e) { calls.push("listener2"); return true; } widget.addEventListener("testRemove", listener1); widget.addEventListener("testRemove", listener2); widget.removeEventListener("testRemove", listener1); widget.dispatchEvent({type:"testRemove"}); expect(calls.length).toBe(1); expect(calls).toContain("listener2"); expect(calls).not.toContain("listener1"); }); it("should prevent adding the same event listener multiple times", function() { var calls = 0; var wiki = $tw.test.wiki(); var widget = createWidgetNode({type:"widget", text:"text"}, wiki); function listener(e) { calls++; return true; } // Add the same listener multiple times widget.addEventListener("testEvent", listener); widget.addEventListener("testEvent", listener); widget.addEventListener("testEvent", listener); // Dispatch the event var event = {type:"testEvent"}; widget.dispatchEvent(event); // The listener should only be called once expect(calls).toBe(1); // Check the internal structure of eventListeners array expect(widget.eventListeners["testEvent"].length).toBe(1); }); });