From de7fe8ba09c597ae2f7bafabe769e23173de7ef2 Mon Sep 17 00:00:00 2001 From: Francis Bouvier Date: Fri, 19 Jan 2024 16:46:09 +0100 Subject: [PATCH] Add tests for Event Signed-off-by: Francis Bouvier --- src/dom/event_target.zig | 3 ++ src/events/event.zig | 85 ++++++++++++++++++++++++++++++++++++++-- src/run_tests.zig | 2 + 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/dom/event_target.zig b/src/dom/event_target.zig index 05fd3f35..b8f32581 100644 --- a/src/dom/event_target.zig +++ b/src/dom/event_target.zig @@ -60,6 +60,8 @@ pub fn testExecFn( var common = [_]Case{ .{ .src = "let content = document.getElementById('content')", .ex = "undefined" }, .{ .src = "let para = document.getElementById('para')", .ex = "undefined" }, + // NOTE: as some event properties will change during the event dispatching phases + // we need to copy thoses values in order to check them afterwards .{ .src = \\var nb = 0; var evt; var phase; var cur; \\function cbk(event) { @@ -121,6 +123,7 @@ pub fn testExecFn( .{ .src = "nb", .ex = "1" }, .{ .src = "evt instanceof Event", .ex = "true" }, .{ .src = "evt.type", .ex = "bubbles" }, + .{ .src = "evt.bubbles", .ex = "true" }, .{ .src = "phase", .ex = "2" }, .{ .src = "cur.getAttribute('id')", .ex = "content" }, }; diff --git a/src/events/event.zig b/src/events/event.zig index 89576cbb..25dd40fe 100644 --- a/src/events/event.zig +++ b/src/events/event.zig @@ -2,6 +2,11 @@ const std = @import("std"); const generate = @import("../generate.zig"); +const jsruntime = @import("jsruntime"); +const Callback = jsruntime.Callback; +const Case = jsruntime.test_utils.Case; +const checkCases = jsruntime.test_utils.checkCases; + const parser = @import("../netsurf.zig"); const DOMException = @import("../dom/exceptions.zig").DOMException; @@ -73,15 +78,15 @@ pub const Event = struct { // Methods - pub fn get_stopPropagation(self: *parser.Event) !void { + pub fn _stopPropagation(self: *parser.Event) !void { return try parser.eventStopPropagation(self); } - pub fn get_stopImmediatePropagation(self: *parser.Event) !void { + pub fn _stopImmediatePropagation(self: *parser.Event) !void { return try parser.eventStopImmediatePropagation(self); } - pub fn get_preventDefault(self: *parser.Event) !void { + pub fn _preventDefault(self: *parser.Event) !void { return try parser.eventPreventDefault(self); } }; @@ -92,3 +97,77 @@ pub const Interfaces = generate.Tuple(.{ }); const Generated = generate.Union.compile(Interfaces); pub const Union = Generated._union; + +pub fn testExecFn( + _: std.mem.Allocator, + js_env: *jsruntime.Env, +) anyerror!void { + var common = [_]Case{ + .{ .src = "let content = document.getElementById('content')", .ex = "undefined" }, + .{ .src = "let para = document.getElementById('para')", .ex = "undefined" }, + .{ .src = "var nb = 0; var evt", .ex = "undefined" }, + }; + try checkCases(js_env, &common); + + var basic = [_]Case{ + .{ .src = + \\content.addEventListener('target', + \\function(e) { + \\evt = e; nb = nb + 1; + \\e.preventDefault(); + \\}) + , .ex = "undefined" }, + .{ .src = "content.dispatchEvent(new Event('target', {bubbles: true, cancelable: true}))", .ex = "false" }, + .{ .src = "nb", .ex = "1" }, + .{ .src = "evt.target === content", .ex = "true" }, + .{ .src = "evt.bubbles", .ex = "true" }, + .{ .src = "evt.cancelable", .ex = "true" }, + .{ .src = "evt.defaultPrevented", .ex = "true" }, + .{ .src = "evt.isTrusted", .ex = "true" }, + .{ .src = "evt.timestamp > 1704063600", .ex = "true" }, // 2024/01/01 00:00 + // event.type, event.currentTarget, event.phase checked in EventTarget + }; + try checkCases(js_env, &basic); + + var stop = [_]Case{ + .{ .src = "nb = 0", .ex = "0" }, + .{ .src = + \\content.addEventListener('stop', + \\function(e) { + \\e.stopPropagation(); + \\nb = nb + 1; + \\}, true) + , .ex = "undefined" }, + // the following event listener will not be invoked + .{ .src = + \\para.addEventListener('stop', + \\function(e) { + \\nb = nb + 1; + \\}) + , .ex = "undefined" }, + .{ .src = "para.dispatchEvent(new Event('stop'))", .ex = "true" }, + .{ .src = "nb", .ex = "1" }, // will be 2 if event was not stopped at content event listener + }; + try checkCases(js_env, &stop); + + var stop_immediate = [_]Case{ + .{ .src = "nb = 0", .ex = "0" }, + .{ .src = + \\content.addEventListener('immediate', + \\function(e) { + \\e.stopImmediatePropagation(); + \\nb = nb + 1; + \\}) + , .ex = "undefined" }, + // the following event listener will not be invoked + .{ .src = + \\content.addEventListener('immediate', + \\function(e) { + \\nb = nb + 1; + \\}) + , .ex = "undefined" }, + .{ .src = "content.dispatchEvent(new Event('immediate'))", .ex = "true" }, + .{ .src = "nb", .ex = "1" }, // will be 2 if event was not stopped at first content event listener + }; + try checkCases(js_env, &stop_immediate); +} diff --git a/src/run_tests.zig b/src/run_tests.zig index f54f5186..22adffe9 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -21,6 +21,7 @@ const DOMTokenListExecFn = @import("dom/token_list.zig").testExecFn; const NodeListTestExecFn = @import("dom/nodelist.zig").testExecFn; const AttrTestExecFn = @import("dom/attribute.zig").testExecFn; const EventTargetTestExecFn = @import("dom/event_target.zig").testExecFn; +const EventTestExecFn = @import("events/event.zig").testExecFn; pub const Types = jsruntime.reflect(apiweb.Interfaces); @@ -75,6 +76,7 @@ fn testsAllExecFn( NodeListTestExecFn, AttrTestExecFn, EventTargetTestExecFn, + EventTestExecFn, }; inline for (testFns) |testFn| {