mirror of
https://github.com/Jermolene/TiddlyWiki5.git
synced 2026-05-30 07:31:57 -07:00
219 lines
6.9 KiB
JavaScript
219 lines
6.9 KiB
JavaScript
/*\
|
|
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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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 = new $tw.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);
|
|
});
|
|
|
|
});
|