mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 22:53:28 +00:00
Migrate some tests to the new htmlRunner
Fix events.get_timeStamp (was events.get_timestamp, wrong casing). Rename `newRunner` to `htmlRunner`. move tests to src/tests (from src/browser/tests). src/runtime and possibly other parts might want to have html tests too.
This commit is contained in:
@@ -112,11 +112,5 @@ pub const Browser = struct {
|
||||
|
||||
const testing = @import("../testing.zig");
|
||||
test "Browser" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
// this will crash if ICU isn't properly configured / ininitialized
|
||||
try runner.testCases(&.{
|
||||
.{ "new Intl.DateTimeFormat()", "[object Intl.DateTimeFormat]" },
|
||||
}, .{});
|
||||
try testing.htmlRunner("browser.html");
|
||||
}
|
||||
|
||||
@@ -66,32 +66,6 @@ const RandomValues = union(enum) {
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.Crypto" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "const a = crypto.randomUUID();", "undefined" },
|
||||
.{ "const b = crypto.randomUUID();", "undefined" },
|
||||
.{ "a.length;", "36" },
|
||||
.{ "b.length;", "36" },
|
||||
.{ "a == b;", "false" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "try { crypto.getRandomValues(new BigUint64Array(8193)) } catch(e) { e.message == 'QuotaExceededError' }", "true" },
|
||||
.{ "let r1 = new Int32Array(5)", "undefined" },
|
||||
.{ "let r2 = crypto.getRandomValues(r1)", "undefined" },
|
||||
.{ "new Set(r1).size", "5" },
|
||||
.{ "new Set(r2).size", "5" },
|
||||
.{ "r1.every((v, i) => v === r2[i])", "true" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "var r3 = new Uint8Array(16)", null },
|
||||
.{ "let r4 = crypto.getRandomValues(r3)", "undefined" },
|
||||
.{ "r4[6] = 10", null },
|
||||
.{ "r4[6]", "10" },
|
||||
.{ "r3[6]", "10" },
|
||||
}, .{});
|
||||
test "Browser: Crypto" {
|
||||
try testing.htmlRunner("crypto.html");
|
||||
}
|
||||
|
||||
@@ -190,12 +190,6 @@ test "parse" {
|
||||
}
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.HTML.CSS" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "CSS.supports('display: flex')", "true" },
|
||||
.{ "CSS.supports('text-decoration-style', 'blink')", "true" },
|
||||
}, .{});
|
||||
test "Browser: CSS" {
|
||||
try testing.htmlRunner("css.html");
|
||||
}
|
||||
|
||||
@@ -79,29 +79,6 @@ pub fn _decode(self: *const TextDecoder, v: []const u8) ![]const u8 {
|
||||
}
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.Encoding.TextDecoder" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{
|
||||
.html = "",
|
||||
});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "let d1 = new TextDecoder();", null },
|
||||
.{ "d1.encoding;", "utf-8" },
|
||||
.{ "d1.fatal", "false" },
|
||||
.{ "d1.ignoreBOM", "false" },
|
||||
.{ "d1.decode(new Uint8Array([240, 160, 174, 183]))", "𠮷" },
|
||||
.{ "d1.decode(new Uint8Array([0xEF, 0xBB, 0xBF, 240, 160, 174, 183]))", "𠮷" },
|
||||
.{ "d1.decode(new Uint8Array([49, 50]).buffer)", "12" },
|
||||
|
||||
.{ "let d2 = new TextDecoder('utf8', {fatal: true})", null },
|
||||
.{
|
||||
\\ try {
|
||||
\\ let data = new Uint8Array([240, 240, 160, 174, 183]);
|
||||
\\ d2.decode(data);
|
||||
\\ } catch (e) {e}
|
||||
,
|
||||
"Error: InvalidUtf8",
|
||||
},
|
||||
}, .{});
|
||||
test "Browser: Encoding.TextDecoder" {
|
||||
try testing.htmlRunner("encoding/decoder.html");
|
||||
}
|
||||
|
||||
@@ -43,20 +43,6 @@ pub fn _encode(_: *const TextEncoder, v: []const u8) !Env.TypedArray(u8) {
|
||||
}
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.Encoding.TextEncoder" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{
|
||||
.html = "",
|
||||
});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "var encoder = new TextEncoder();", null },
|
||||
.{ "encoder.encoding;", "utf-8" },
|
||||
.{ "encoder.encode('€');", "226,130,172" },
|
||||
|
||||
// Invalid utf-8 sequence.
|
||||
// Result with chrome:
|
||||
// .{ "encoder.encode(new Uint8Array([0xE2,0x28,0xA1]))", "50,50,54,44,52,48,44,49,54,49" },
|
||||
.{ "try {encoder.encode(new Uint8Array([0xE2,0x28,0xA1])) } catch (e) { e };", "Error: InvalidUtf8" },
|
||||
}, .{});
|
||||
test "Browser: Encoding.TextEncoder" {
|
||||
try testing.htmlRunner("encoding/encoder.html");
|
||||
}
|
||||
|
||||
@@ -58,23 +58,6 @@ pub const CustomEvent = struct {
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.CustomEvent" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "let capture = null", "undefined" },
|
||||
.{ "const el = document.createElement('div');", "undefined" },
|
||||
.{ "el.addEventListener('c1', (e) => { capture = 'c1-' + new String(e.detail)})", "undefined" },
|
||||
.{ "el.addEventListener('c2', (e) => { capture = 'c2-' + new String(e.detail.over)})", "undefined" },
|
||||
|
||||
.{ "el.dispatchEvent(new CustomEvent('c1'));", "true" },
|
||||
.{ "capture", "c1-null" },
|
||||
|
||||
.{ "el.dispatchEvent(new CustomEvent('c1', {detail: '123'}));", "true" },
|
||||
.{ "capture", "c1-123" },
|
||||
|
||||
.{ "el.dispatchEvent(new CustomEvent('c2', {detail: {over: 9000}}));", "true" },
|
||||
.{ "capture", "c2-9000" },
|
||||
}, .{});
|
||||
test "Browser: Events.Custom" {
|
||||
try testing.htmlRunner("events/custom.html");
|
||||
}
|
||||
|
||||
@@ -110,8 +110,11 @@ pub const Event = struct {
|
||||
return try parser.eventIsTrusted(self);
|
||||
}
|
||||
|
||||
pub fn get_timestamp(self: *parser.Event) !u32 {
|
||||
return try parser.eventTimestamp(self);
|
||||
// Even though this is supposed to to provide microsecond resolution, browser
|
||||
// return coarser values to protect against fingerprinting. libdom returns
|
||||
// seconds, which is good enough.
|
||||
pub fn get_timeStamp(self: *parser.Event) !u32 {
|
||||
return parser.eventTimestamp(self);
|
||||
}
|
||||
|
||||
// Methods
|
||||
@@ -386,155 +389,6 @@ const SignalCallback = struct {
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.Event" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "let content = document.getElementById('content')", "undefined" },
|
||||
.{ "let para = document.getElementById('para')", "undefined" },
|
||||
.{ "var nb = 0; var evt", "undefined" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{
|
||||
\\ content.addEventListener('target', function(e) {
|
||||
\\ evt = e; nb = nb + 1;
|
||||
\\ e.preventDefault();
|
||||
\\ })
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
.{ "content.dispatchEvent(new Event('target', {bubbles: true, cancelable: true}))", "false" },
|
||||
.{ "nb", "1" },
|
||||
.{ "evt.target === content", "true" },
|
||||
.{ "evt.bubbles", "true" },
|
||||
.{ "evt.cancelable", "true" },
|
||||
.{ "evt.defaultPrevented", "true" },
|
||||
.{ "evt.isTrusted", "true" },
|
||||
.{ "evt.timestamp > 1704063600", "true" }, // 2024/01/01 00:00
|
||||
// event.type, event.currentTarget, event.phase checked in EventTarget
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "nb = 0", "0" },
|
||||
.{
|
||||
\\ content.addEventListener('stop',function(e) {
|
||||
\\ e.stopPropagation();
|
||||
\\ nb = nb + 1;
|
||||
\\ }, true)
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
// the following event listener will not be invoked
|
||||
.{
|
||||
\\ para.addEventListener('stop',function(e) {
|
||||
\\ nb = nb + 1;
|
||||
\\ })
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
.{ "para.dispatchEvent(new Event('stop'))", "true" },
|
||||
.{ "nb", "1" }, // will be 2 if event was not stopped at content event listener
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "nb = 0", "0" },
|
||||
.{
|
||||
\\ content.addEventListener('immediate', function(e) {
|
||||
\\ e.stopImmediatePropagation();
|
||||
\\ nb = nb + 1;
|
||||
\\ })
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
// the following event listener will not be invoked
|
||||
.{
|
||||
\\ content.addEventListener('immediate', function(e) {
|
||||
\\ nb = nb + 1;
|
||||
\\ })
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
.{ "content.dispatchEvent(new Event('immediate'))", "true" },
|
||||
.{ "nb", "1" }, // will be 2 if event was not stopped at first content event listener
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "nb = 0", "0" },
|
||||
.{
|
||||
\\ content.addEventListener('legacy', function(e) {
|
||||
\\ evt = e; nb = nb + 1;
|
||||
\\ })
|
||||
,
|
||||
"undefined",
|
||||
},
|
||||
.{ "let evtLegacy = document.createEvent('Event')", "undefined" },
|
||||
.{ "evtLegacy.initEvent('legacy')", "undefined" },
|
||||
.{ "content.dispatchEvent(evtLegacy)", "true" },
|
||||
.{ "nb", "1" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "var nb = 0; var evt = null; function cbk(event) { nb ++; evt=event; }", "undefined" },
|
||||
.{ "document.addEventListener('count', cbk)", "undefined" },
|
||||
.{ "document.removeEventListener('count', cbk)", "undefined" },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "nb", "0" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "nb = 0; function cbk(event) { nb ++; }", null },
|
||||
.{ "document.addEventListener('count', cbk, {once: true})", null },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "nb", "1" },
|
||||
.{ "document.removeEventListener('count', cbk)", "undefined" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "nb = 0; function cbk(event) { nb ++; }", null },
|
||||
.{ "let ac = new AbortController()", null },
|
||||
.{ "document.addEventListener('count', cbk, {signal: ac.signal})", null },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "ac.abort()", null },
|
||||
.{ "document.dispatchEvent(new Event('count'))", "true" },
|
||||
.{ "nb", "2" },
|
||||
.{ "document.removeEventListener('count', cbk)", "undefined" },
|
||||
}, .{});
|
||||
|
||||
try runner.testCases(&.{
|
||||
.{ "new Event('').composedPath()", "" },
|
||||
.{
|
||||
\\ let div1 = document.createElement('div');
|
||||
\\ let sr1 = div1.attachShadow({mode: 'open'});
|
||||
\\ sr1.innerHTML = "<p id=srp1></p>";
|
||||
\\ document.getElementsByTagName('body')[0].appendChild(div1);
|
||||
\\ let cp = null;
|
||||
\\ div1.addEventListener('click', (e) => {
|
||||
\\ cp = e.composedPath().map((n) => n.id || n.nodeName || n.toString());
|
||||
\\ });
|
||||
\\ sr1.getElementById('srp1').click();
|
||||
\\ cp.join(', ');
|
||||
,
|
||||
"srp1, #document-fragment, DIV, BODY, HTML, #document, [object Window]",
|
||||
},
|
||||
|
||||
.{
|
||||
\\ let div2 = document.createElement('div');
|
||||
\\ let sr2 = div2.attachShadow({mode: 'closed'});
|
||||
\\ sr2.innerHTML = "<p id=srp2></p>";
|
||||
\\ document.getElementsByTagName('body')[0].appendChild(div2);
|
||||
\\ cp = null;
|
||||
\\ div2.addEventListener('click', (e) => {
|
||||
\\ cp = e.composedPath().map((n) => n.id || n.nodeName || n.toString());
|
||||
\\ });
|
||||
\\ sr2.getElementById('srp2').click();
|
||||
\\ cp.join(', ');
|
||||
,
|
||||
"DIV, BODY, HTML, #document, [object Window]",
|
||||
},
|
||||
}, .{});
|
||||
test "Browser: Event" {
|
||||
try testing.htmlRunner("events/event.html");
|
||||
}
|
||||
|
||||
@@ -107,34 +107,6 @@ pub const MouseEvent = struct {
|
||||
};
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser.MouseEvent" {
|
||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
|
||||
defer runner.deinit();
|
||||
|
||||
try runner.testCases(&.{
|
||||
// Default MouseEvent
|
||||
.{ "let event = new MouseEvent('click')", "undefined" },
|
||||
.{ "event.type", "click" },
|
||||
.{ "event instanceof MouseEvent", "true" },
|
||||
.{ "event instanceof Event", "true" },
|
||||
.{ "event.clientX", "0" },
|
||||
.{ "event.clientY", "0" },
|
||||
.{ "event.screenX", "0" },
|
||||
.{ "event.screenY", "0" },
|
||||
// MouseEvent with parameters
|
||||
.{ "let new_event = new MouseEvent('click', { 'button': 0, 'clientX': 10, 'clientY': 20 })", "undefined" },
|
||||
.{ "new_event.button", "0" },
|
||||
.{ "new_event.x", "10" },
|
||||
.{ "new_event.y", "20" },
|
||||
.{ "new_event.screenX", "10" },
|
||||
.{ "new_event.screenY", "20" },
|
||||
// MouseEvent Listener
|
||||
.{ "let me = new MouseEvent('click')", "undefined" },
|
||||
.{ "me instanceof Event", "true" },
|
||||
.{ "var eevt = null; function ccbk(event) { eevt = event; }", "undefined" },
|
||||
.{ "document.addEventListener('click', ccbk)", "undefined" },
|
||||
.{ "document.dispatchEvent(me)", "true" },
|
||||
.{ "eevt.type", "click" },
|
||||
.{ "eevt instanceof MouseEvent", "true" },
|
||||
}, .{});
|
||||
test "Browser: Events.Mouse" {
|
||||
try testing.htmlRunner("events/mouse.html");
|
||||
}
|
||||
|
||||
@@ -439,6 +439,6 @@ const TimerCallback = struct {
|
||||
|
||||
const testing = @import("../../testing.zig");
|
||||
test "Browser: Window" {
|
||||
try testing.newRunner("window/window.html");
|
||||
try testing.newRunner("window/frames.html");
|
||||
try testing.htmlRunner("window/window.html");
|
||||
try testing.htmlRunner("window/frames.html");
|
||||
}
|
||||
|
||||
@@ -796,7 +796,7 @@ fn testHTTPHandler(req: *std.http.Server.Request) !void {
|
||||
});
|
||||
}
|
||||
|
||||
if (std.mem.startsWith(u8, path, "/src/browser/tests/")) {
|
||||
if (std.mem.startsWith(u8, path, "/src/tests/")) {
|
||||
// strip off leading / so that it's relative to CWD
|
||||
return TestHTTPServer.sendFile(req, path[1..]);
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ pub fn shutdown() void {
|
||||
test_app.deinit();
|
||||
}
|
||||
|
||||
pub fn newRunner(file: []const u8) !void {
|
||||
pub fn htmlRunner(file: []const u8) !void {
|
||||
defer _ = arena_instance.reset(.retain_capacity);
|
||||
const page = try test_session.createPage();
|
||||
defer test_session.removePage();
|
||||
@@ -516,7 +516,7 @@ pub fn newRunner(file: []const u8) !void {
|
||||
try_catch.init(js_context);
|
||||
defer try_catch.deinit();
|
||||
|
||||
const url = try std.fmt.allocPrint(arena_allocator, "http://localhost:9582/src/browser/tests/{s}", .{file});
|
||||
const url = try std.fmt.allocPrint(arena_allocator, "http://localhost:9582/src/tests/{s}", .{file});
|
||||
try page.navigate(url, .{});
|
||||
page.wait(2);
|
||||
|
||||
|
||||
5
src/tests/browser.html
Normal file
5
src/tests/browser.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<script src="testing.js"></script>
|
||||
<script id=intl>
|
||||
// this will crash if ICU isn't properly configured / ininitialized
|
||||
testing.expectEqual("[object Intl.DateTimeFormat]", new Intl.DateTimeFormat().toString());
|
||||
</script>
|
||||
25
src/tests/crypto.html
Normal file
25
src/tests/crypto.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<script src="testing.js"></script>
|
||||
<script id=crypto>
|
||||
const a = crypto.randomUUID();
|
||||
const b = crypto.randomUUID();
|
||||
testing.expectEqual(36, a.length);
|
||||
testing.expectEqual(36, b.length);
|
||||
testing.expectEqual(false, a == b)
|
||||
|
||||
testing.expectError('Error: QuotaExceededError', () => {
|
||||
crypto.getRandomValues(new BigUint64Array(8193));
|
||||
});
|
||||
|
||||
let r1 = new Int32Array(5)
|
||||
let r2 = crypto.getRandomValues(r1)
|
||||
testing.expectEqual(5, new Set(r1).size);
|
||||
testing.expectEqual(5, new Set(r2).size);
|
||||
testing.expectEqual(true, r1.every((v, i) => v === r2[i]));
|
||||
|
||||
var r3 = new Uint8Array(16);
|
||||
let r4 = crypto.getRandomValues(r3);
|
||||
|
||||
r4[6] = 10;
|
||||
testing.expectEqual(10, r4[6]);
|
||||
testing.expectEqual(10, r3[6]);
|
||||
</script>
|
||||
5
src/tests/css.html
Normal file
5
src/tests/css.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<script src="testing.js"></script>
|
||||
<script id=support>
|
||||
testing.expectEqual(true, CSS.supports('display: flex'));
|
||||
testing.expectEqual(true, CSS.supports('text-decoration-style', 'blink'));
|
||||
</script>
|
||||
17
src/tests/encoding/decoder.html
Normal file
17
src/tests/encoding/decoder.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<script src="../testing.js"></script>
|
||||
<script id=decoder>
|
||||
let d1 = new TextDecoder();
|
||||
testing.expectEqual('utf-8', d1.encoding);
|
||||
testing.expectEqual(false, d1.fatal);
|
||||
testing.expectEqual(false, d1.ignoreBOM);
|
||||
|
||||
testing.expectEqual('𠮷', d1.decode(new Uint8Array([240, 160, 174, 183])));
|
||||
testing.expectEqual('𠮷', d1.decode(new Uint8Array([0xEF, 0xBB, 0xBF, 240, 160, 174, 183])));
|
||||
testing.expectEqual('<27>2', d1.decode(new Uint8Array([249, 50])));
|
||||
|
||||
let d2 = new TextDecoder('utf8', {fatal: true})
|
||||
testing.expectError('Error: InvalidUtf8', () => {
|
||||
let data = new Uint8Array([240, 240, 160, 174, 183]);
|
||||
d2.decode(data);
|
||||
});
|
||||
</script>
|
||||
13
src/tests/encoding/encoder.html
Normal file
13
src/tests/encoding/encoder.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<script src="../testing.js"></script>
|
||||
<script id=encoder>
|
||||
var encoder = new TextEncoder();
|
||||
testing.expectEqual('utf-8', encoder.encoding);
|
||||
testing.expectEqual([226, 130, 172], Array.from(encoder.encode('€')));
|
||||
|
||||
// Invalid utf-8 sequence.
|
||||
// Browsers give a different result for this, they decode it to:
|
||||
// 50, 50, 54, 44, 52, 48, 44, 49, 54, 49
|
||||
testing.expectError('Error: InvalidUtf8', () => {
|
||||
encoder.encode(new Uint8Array([0xE2,0x28,0xA1]));
|
||||
});
|
||||
</script>
|
||||
16
src/tests/events/custom.html
Normal file
16
src/tests/events/custom.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<script src="../testing.js"></script>
|
||||
<script id=custom>
|
||||
let capture = null;
|
||||
const el = document.createElement('div');
|
||||
el.addEventListener('c1', (e) => { capture = 'c1-' + new String(e.detail)});
|
||||
el.addEventListener('c2', (e) => { capture = 'c2-' + new String(e.detail.over)});
|
||||
|
||||
el.dispatchEvent(new CustomEvent('c1'));
|
||||
testing.expectEqual("c1-null", capture);
|
||||
|
||||
el.dispatchEvent(new CustomEvent('c1', {detail: '123'}));
|
||||
testing.expectEqual("c1-123", capture);
|
||||
|
||||
el.dispatchEvent(new CustomEvent('c2', {detail: {over: 9000}}));
|
||||
testing.expectEqual("c2-9000", capture);
|
||||
</script>
|
||||
138
src/tests/events/event.html
Normal file
138
src/tests/events/event.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<script src="../testing.js"></script>
|
||||
|
||||
<div id=content>
|
||||
<p id="para"></p>
|
||||
</div>
|
||||
|
||||
<script id=dispatch>
|
||||
const startTime = new Date().getTime();
|
||||
|
||||
let content = $('#content');
|
||||
// let para = document.getElementById('para');
|
||||
var nb = 0;
|
||||
var evt = null;
|
||||
|
||||
const incrementCallback = function(e) {
|
||||
evt = e;
|
||||
nb += 1;
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
content.addEventListener('dispatch', incrementCallback);
|
||||
|
||||
content.dispatchEvent(new Event('dispatch', {bubbles: true, cancelable: true}));
|
||||
testing.expectEqual(1, nb);
|
||||
testing.expectEqual(content, evt.target);
|
||||
testing.expectEqual(true, evt.bubbles);
|
||||
testing.expectEqual(true, evt.cancelable);
|
||||
testing.expectEqual(true, evt.defaultPrevented);
|
||||
testing.expectEqual(true, evt.isTrusted);
|
||||
testing.expectEqual(true, evt.timeStamp >= Math.floor(startTime/1000));
|
||||
</script>
|
||||
|
||||
<script id=propogate>
|
||||
nb = 0;
|
||||
let para = $('#para');
|
||||
// the stop listener is capturing, so it propogates down
|
||||
content.addEventListener('stop',function(e) {
|
||||
e.stopPropagation();
|
||||
nb += 1;
|
||||
}, true)
|
||||
|
||||
para.addEventListener('stop',function(e) {
|
||||
nb += 10;
|
||||
});
|
||||
|
||||
para.dispatchEvent(new Event('stop'));
|
||||
// didn't propogate down (because of capturing) to para handler
|
||||
testing.expectEqual(1, nb);
|
||||
</script>
|
||||
|
||||
<script id=immediate>
|
||||
nb = 0;
|
||||
|
||||
content.addEventListener('immediate', function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
nb += 1;
|
||||
});
|
||||
|
||||
// the following event listener will not be invoked
|
||||
content.addEventListener('immediate', function(e) {
|
||||
nb += 10;
|
||||
});
|
||||
|
||||
content.dispatchEvent(new Event('immediate'));
|
||||
testing.expectEqual(1, nb);
|
||||
</script>
|
||||
|
||||
<script id=legacy>
|
||||
nb = 0;
|
||||
content.addEventListener('legacy', incrementCallback);
|
||||
let evtLegacy = document.createEvent('Event');
|
||||
evtLegacy.initEvent('legacy');
|
||||
content.dispatchEvent(evtLegacy);
|
||||
testing.expectEqual(1, nb);
|
||||
</script>
|
||||
|
||||
<script id=removeListener>
|
||||
nb = 0;
|
||||
document.addEventListener('count', incrementCallback);
|
||||
document.removeEventListener('count', incrementCallback);
|
||||
document.dispatchEvent(new Event('count'));
|
||||
testing.expectEqual(0, nb);
|
||||
</script>
|
||||
|
||||
<script id=once>
|
||||
document.addEventListener('count', incrementCallback, {once: true});
|
||||
document.dispatchEvent(new Event('count'));
|
||||
document.dispatchEvent(new Event('count'));
|
||||
document.dispatchEvent(new Event('count'));
|
||||
testing.expectEqual(1, nb);
|
||||
</script>
|
||||
|
||||
<script id=abortController>
|
||||
nb = 0;
|
||||
|
||||
let ac = new AbortController()
|
||||
document.addEventListener('count', incrementCallback, {signal: ac.signal})
|
||||
document.dispatchEvent(new Event('count'));
|
||||
document.dispatchEvent(new Event('count'));
|
||||
ac.abort();
|
||||
document.dispatchEvent(new Event('count'));
|
||||
testing.expectEqual(2, nb);
|
||||
document.removeEventListener('count', incrementCallback);
|
||||
</script>
|
||||
|
||||
<script id=composedPath>
|
||||
testing.expectEqual([], new Event('').composedPath());
|
||||
|
||||
let div1 = document.createElement('div');
|
||||
let sr1 = div1.attachShadow({mode: 'open'});
|
||||
sr1.innerHTML = "<p id=srp1></p>";
|
||||
document.getElementsByTagName('body')[0].appendChild(div1);
|
||||
|
||||
let cp = null;
|
||||
const shadowCallback = function(e) {
|
||||
cp = e.composedPath().map((n) => n.id || n.nodeName || n.toString());
|
||||
}
|
||||
|
||||
div1.addEventListener('click', shadowCallback);
|
||||
sr1.getElementById('srp1').click();
|
||||
testing.expectEqual(
|
||||
['srp1', '#document-fragment', 'DIV', 'BODY', 'HTML', '#document', '[object Window]'],
|
||||
cp
|
||||
);
|
||||
|
||||
let div2 = document.createElement('div');
|
||||
let sr2 = div2.attachShadow({mode: 'closed'});
|
||||
sr2.innerHTML = "<p id=srp2></p>";
|
||||
document.getElementsByTagName('body')[0].appendChild(div2);
|
||||
|
||||
cp = null;
|
||||
div2.addEventListener('click', shadowCallback);
|
||||
sr2.getElementById('srp2').click();
|
||||
testing.expectEqual(
|
||||
['DIV', 'BODY', 'HTML', '#document', '[object Window]'],
|
||||
cp
|
||||
);
|
||||
</script>
|
||||
33
src/tests/events/mouse.html
Normal file
33
src/tests/events/mouse.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<script src="../testing.js"></script>
|
||||
<script id=default>
|
||||
let event = new MouseEvent('click');
|
||||
testing.expectEqual('click', event.type);
|
||||
testing.expectEqual(true, event instanceof MouseEvent);
|
||||
testing.expectEqual(true, event instanceof Event);
|
||||
testing.expectEqual(0, event.clientX);
|
||||
testing.expectEqual(0, event.clientY);
|
||||
testing.expectEqual(0, event.screenX);
|
||||
testing.expectEqual(0, event.screenY);
|
||||
</script>
|
||||
|
||||
<script id=parameters>
|
||||
let new_event = new MouseEvent('click', { 'button': 0, 'clientX': 10, 'clientY': 20 });
|
||||
testing.expectEqual(0, new_event.button);
|
||||
testing.expectEqual(10, new_event.x);
|
||||
testing.expectEqual(20, new_event.y);
|
||||
testing.expectEqual(10, new_event.screenX);
|
||||
testing.expectEqual(20, new_event.screenY);
|
||||
</script>
|
||||
|
||||
<script id=listener>
|
||||
let me = new MouseEvent('click');
|
||||
testing.expectEqual(true, me instanceof Event);
|
||||
|
||||
var evt = null;
|
||||
document.addEventListener('click', function (e) {
|
||||
evt = e;
|
||||
});
|
||||
document.dispatchEvent(me);
|
||||
testing.expectEqual('click', evt.type);
|
||||
testing.expectEqual(true, evt instanceof MouseEvent);
|
||||
</script>
|
||||
@@ -13,16 +13,17 @@
|
||||
(() => {
|
||||
function expectEqual(expected, actual) {
|
||||
_recordExecution();
|
||||
if (expected !== actual) {
|
||||
testing._status = 'fail';
|
||||
let msg = `expected: ${JSON.stringify(expected)}, got: ${JSON.stringify(actual)}`;
|
||||
|
||||
console.warn(
|
||||
`id: ${testing._captured?.script_id || document.currentScript.id}`,
|
||||
`msg: ${msg}`,
|
||||
`stack: ${testing._captured?.stack || new Error().stack}`,
|
||||
);
|
||||
if (_equal(expected, actual)) {
|
||||
return;
|
||||
}
|
||||
testing._status = 'fail';
|
||||
let msg = `expected: ${JSON.stringify(expected)}, got: ${JSON.stringify(actual)}`;
|
||||
|
||||
console.warn(
|
||||
`id: ${testing._captured?.script_id || document.currentScript.id}`,
|
||||
`msg: ${msg}`,
|
||||
`stack: ${testing._captured?.stack || new Error().stack}`,
|
||||
);
|
||||
}
|
||||
|
||||
function expectError(expected, fn) {
|
||||
@@ -41,6 +42,7 @@
|
||||
expectEqual('an error', null);
|
||||
}
|
||||
|
||||
// Should only be called by the test runner
|
||||
function getStatus() {
|
||||
// if we're already in a fail state, return fail, nothing can recover this
|
||||
if (testing._status === 'fail') return 'fail';
|
||||
@@ -97,6 +99,8 @@
|
||||
_registerErrorCallback();
|
||||
}
|
||||
|
||||
// We want to attach an onError callback to each <script>, so that we can
|
||||
// properly fail it.
|
||||
function _registerErrorCallback() {
|
||||
const script = document.currentScript;
|
||||
if (!script) {
|
||||
@@ -120,6 +124,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
function _equal(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a === null || b === null) {
|
||||
return false;
|
||||
}
|
||||
if (typeof a !== 'object' || typeof b !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Object.keys(a).length != Object.keys(b).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (property in a) {
|
||||
if (b.hasOwnProperty(property) === false) {
|
||||
return false;
|
||||
}
|
||||
if (_equal(a[property], b[property]) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
window.testing = {
|
||||
_status: 'empty',
|
||||
_eventually: [],
|
||||
Reference in New Issue
Block a user