From a0374133cd42e2944be3852c2c31d41120d5827f Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 3 Sep 2025 14:59:07 +0800 Subject: [PATCH 1/2] migrate tests to new html runner --- src/browser/polyfill/webcomponents.zig | 29 ++------------------------ src/browser/storage/storage.zig | 24 +++------------------ src/tests/polyfill/webcomponents.html | 22 +++++++++++++++++++ src/tests/storage/local_storage.html | 25 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 48 deletions(-) create mode 100644 src/tests/polyfill/webcomponents.html create mode 100644 src/tests/storage/local_storage.html diff --git a/src/browser/polyfill/webcomponents.zig b/src/browser/polyfill/webcomponents.zig index 2f4f44cd..6c32f126 100644 --- a/src/browser/polyfill/webcomponents.zig +++ b/src/browser/polyfill/webcomponents.zig @@ -37,31 +37,6 @@ pub const pre = ; const testing = @import("../../testing.zig"); -test "Browser.webcomponents" { - var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html = "
" }); - defer runner.deinit(); - - try @import("polyfill.zig").preload(testing.allocator, runner.page.main_context); - - try runner.testCases(&.{ - .{ - \\ class LightPanda extends HTMLElement { - \\ constructor() { - \\ super(); - \\ } - \\ connectedCallback() { - \\ this.append('connected'); - \\ } - \\ } - \\ window.customElements.define("lightpanda-test", LightPanda); - \\ const main = document.getElementById('main'); - \\ main.appendChild(document.createElement('lightpanda-test')); - , - null, - }, - - .{ "main.innerHTML", "connected" }, - .{ "document.createElement('lightpanda-test').dataset", "[object DataSet]" }, - .{ "document.createElement('lightpanda-test.x').dataset", "[object DataSet]" }, - }, .{}); +test "Browser: Polyfill.WebComponents" { + try testing.htmlRunner("polyfill/webcomponents.html"); } diff --git a/src/browser/storage/storage.zig b/src/browser/storage/storage.zig index 7b00a223..d68342b5 100644 --- a/src/browser/storage/storage.zig +++ b/src/browser/storage/storage.zig @@ -208,29 +208,11 @@ pub const Bottle = struct { // ----- const testing = @import("../../testing.zig"); -test "Browser.Storage.LocalStorage" { - var runner = try testing.jsRunner(testing.tracking_allocator, .{}); - defer runner.deinit(); - - try runner.testCases(&.{ - .{ "localStorage.length", "0" }, - - .{ "localStorage.setItem('foo', 'bar')", "undefined" }, - .{ "localStorage.length", "1" }, - .{ "localStorage.getItem('foo')", "bar" }, - .{ "localStorage.removeItem('foo')", "undefined" }, - .{ "localStorage.length", "0" }, - - // .{ "localStorage['foo'] = 'bar'", "undefined" }, - // .{ "localStorage['foo']", "bar" }, - // .{ "localStorage.length", "1" }, - - .{ "localStorage.clear()", "undefined" }, - .{ "localStorage.length", "0" }, - }, .{}); +test "Browser: Storage.LocalStorage" { + try testing.htmlRunner("storage/local_storage.html"); } -test "storage bottle" { +test "Browser: Storage.Bottle" { var bottle = Bottle.init(std.testing.allocator); defer bottle.deinit(); diff --git a/src/tests/polyfill/webcomponents.html b/src/tests/polyfill/webcomponents.html new file mode 100644 index 00000000..bc47c882 --- /dev/null +++ b/src/tests/polyfill/webcomponents.html @@ -0,0 +1,22 @@ + + +
+ + diff --git a/src/tests/storage/local_storage.html b/src/tests/storage/local_storage.html new file mode 100644 index 00000000..d4605844 --- /dev/null +++ b/src/tests/storage/local_storage.html @@ -0,0 +1,25 @@ + + + From 0382c2775e196ed7d48726bcdfd64010f6d75d14 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 3 Sep 2025 16:40:01 +0800 Subject: [PATCH 2/2] Migrate more tests to html runner Implement LocalStorage named get/set (i.e. localStorage["hi"]) --- src/browser/storage/storage.zig | 12 +- src/browser/url/url.zig | 161 +-------------------------- src/tests/storage/local_storage.html | 7 +- src/tests/url/url.html | 77 +++++++++++++ src/tests/url/url_search_params.html | 93 ++++++++++++++++ 5 files changed, 189 insertions(+), 161 deletions(-) create mode 100644 src/tests/url/url.html create mode 100644 src/tests/url/url_search_params.html diff --git a/src/browser/storage/storage.zig b/src/browser/storage/storage.zig index d68342b5..9e061213 100644 --- a/src/browser/storage/storage.zig +++ b/src/browser/storage/storage.zig @@ -130,7 +130,7 @@ pub const Bottle = struct { return @intCast(self.map.count()); } - pub fn _key(self: *Bottle, idx: u32) ?[]const u8 { + pub fn _key(self: *const Bottle, idx: u32) ?[]const u8 { if (idx >= self.map.count()) return null; var it = self.map.valueIterator(); @@ -142,7 +142,7 @@ pub const Bottle = struct { unreachable; } - pub fn _getItem(self: *Bottle, k: []const u8) ?[]const u8 { + pub fn _getItem(self: *const Bottle, k: []const u8) ?[]const u8 { return self.map.get(k); } @@ -202,6 +202,14 @@ pub const Bottle = struct { // // So for now, we won't impement the feature. } + + pub fn named_get(self: *const Bottle, name: []const u8, _: *bool) ?[]const u8 { + return self._getItem(name); + } + + pub fn named_set(self: *Bottle, name: []const u8, value: []const u8, _: *bool) !void { + try self._setItem(name, value); + } }; // Tests diff --git a/src/browser/url/url.zig b/src/browser/url/url.zig index 625e1452..0be14e0d 100644 --- a/src/browser/url/url.zig +++ b/src/browser/url/url.zig @@ -501,163 +501,10 @@ const ValueIterable = iterator.Iterable(kv.ValueIterator, "URLSearchParamsValueI const EntryIterable = iterator.Iterable(kv.EntryIterator, "URLSearchParamsEntryIterator"); const testing = @import("../../testing.zig"); -test "Browser.URL" { - var runner = try testing.jsRunner(testing.tracking_allocator, .{}); - defer runner.deinit(); - - try runner.testCases(&.{ - .{ "var url = new URL('https://foo.bar/path?query#fragment')", "undefined" }, - .{ "url.origin", "https://foo.bar" }, - .{ "url.href", "https://foo.bar/path?query#fragment" }, - .{ "url.protocol", "https:" }, - .{ "url.username", "" }, - .{ "url.password", "" }, - .{ "url.host", "foo.bar" }, - .{ "url.hostname", "foo.bar" }, - .{ "url.port", "" }, - .{ "url.pathname", "/path" }, - .{ "url.search", "?query" }, - .{ "url.hash", "#fragment" }, - .{ "url.searchParams.get('query')", "" }, - - .{ "url.search = 'hello=world'", null }, - .{ "url.searchParams.size", "1" }, - .{ "url.searchParams.get('hello')", "world" }, - - .{ "url.search = '?over=9000'", null }, - .{ "url.searchParams.size", "1" }, - .{ "url.searchParams.get('over')", "9000" }, - - .{ "url.search = ''", null }, - .{ "url.searchParams.size", "0" }, - - .{ " const url2 = new URL(url);", null }, - .{ "url2.href", "https://foo.bar/path#fragment" }, - - .{ " try { new URL(document.createElement('a')); } catch (e) { e }", "TypeError: invalid argument" }, - - .{ " let a = document.createElement('a');", null }, - .{ " a.href = 'https://www.lightpanda.io/over?9000=!!';", null }, - .{ " const url3 = new URL(a);", null }, - .{ "url3.href", "https://www.lightpanda.io/over?9000=%21%21" }, - }, .{}); - - try runner.testCases(&.{ - .{ "var url = new URL('https://foo.bar/path?a=~&b=%7E#fragment')", "undefined" }, - .{ "url.searchParams.get('a')", "~" }, - .{ "url.searchParams.get('b')", "~" }, - .{ "url.searchParams.append('c', 'foo')", "undefined" }, - .{ "url.searchParams.get('c')", "foo" }, - .{ "url.searchParams.getAll('c').length", "1" }, - .{ "url.searchParams.getAll('c')[0]", "foo" }, - .{ "url.searchParams.size", "3" }, - - // search is dynamic - .{ "url.search", "?a=~&b=~&c=foo" }, - // href is dynamic - .{ "url.href", "https://foo.bar/path?a=~&b=~&c=foo#fragment" }, - - .{ "url.searchParams.delete('c', 'foo')", "undefined" }, - .{ "url.searchParams.get('c')", "null" }, - .{ "url.searchParams.delete('a')", "undefined" }, - .{ "url.searchParams.get('a')", "null" }, - }, .{}); - - try runner.testCases(&.{ - .{ "var url = new URL('over?9000', 'https://lightpanda.io')", null }, - .{ "url.href", "https://lightpanda.io/over?9000" }, - }, .{}); - - try runner.testCases(&.{ - .{ "let sk = new URL('sveltekit-internal://')", null }, - .{ "sk.protocol", "sveltekit-internal:" }, - .{ "sk.host", "" }, - .{ "sk.hostname", "" }, - .{ "sk.href", "sveltekit-internal://" }, - }, .{}); +test "Browser: URL" { + try testing.htmlRunner("url/url.html"); } -test "Browser.URLSearchParams" { - var runner = try testing.jsRunner(testing.tracking_allocator, .{}); - defer runner.deinit(); - try runner.testCases(&.{ - .{ "let usp = new URLSearchParams()", null }, - .{ "usp.get('a')", "null" }, - .{ "usp.has('a')", "false" }, - .{ "usp.getAll('a')", "" }, - .{ "usp.delete('a')", "undefined" }, - - .{ "usp.set('a', 1)", "undefined" }, - .{ "usp.has('a')", "true" }, - .{ "usp.get('a')", "1" }, - .{ "usp.getAll('a')", "1" }, - - .{ "usp.append('a', 2)", "undefined" }, - .{ "usp.has('a')", "true" }, - .{ "usp.get('a')", "1" }, - .{ "usp.getAll('a')", "1,2" }, - - .{ "usp.append('b', '3')", "undefined" }, - .{ "usp.has('a')", "true" }, - .{ "usp.get('a')", "1" }, - .{ "usp.getAll('a')", "1,2" }, - .{ "usp.has('b')", "true" }, - .{ "usp.get('b')", "3" }, - .{ "usp.getAll('b')", "3" }, - - .{ "let acc = [];", null }, - .{ "for (const key of usp.keys()) { acc.push(key) }; acc;", "a,a,b" }, - - .{ "acc = [];", null }, - .{ "for (const value of usp.values()) { acc.push(value) }; acc;", "1,2,3" }, - - .{ "acc = [];", null }, - .{ "for (const entry of usp.entries()) { acc.push(entry) }; acc;", "a,1,a,2,b,3" }, - - .{ "acc = [];", null }, - .{ "for (const entry of usp) { acc.push(entry) }; acc;", "a,1,a,2,b,3" }, - - .{ "usp.delete('a')", "undefined" }, - .{ "usp.has('a')", "false" }, - .{ "usp.has('b')", "true" }, - - .{ "acc = [];", null }, - .{ "for (const key of usp.keys()) { acc.push(key) }; acc;", "b" }, - - .{ "acc = [];", null }, - .{ "for (const value of usp.values()) { acc.push(value) }; acc;", "3" }, - - .{ "acc = [];", null }, - .{ "for (const entry of usp.entries()) { acc.push(entry) }; acc;", "b,3" }, - - .{ "acc = [];", null }, - .{ "for (const entry of usp) { acc.push(entry) }; acc;", "b,3" }, - }, .{}); - - try runner.testCases(&.{ - .{ "usp = new URLSearchParams('?hello')", null }, - .{ "usp.get('hello')", "" }, - - .{ "usp = new URLSearchParams('?abc=')", null }, - .{ "usp.get('abc')", "" }, - - .{ "usp = new URLSearchParams('?abc=123&')", null }, - .{ "usp.get('abc')", "123" }, - .{ "usp.size", "1" }, - - .{ "var fd = new FormData()", null }, - .{ "fd.append('a', '1')", null }, - .{ "fd.append('a', '2')", null }, - .{ "fd.append('b', '3')", null }, - .{ "ups = new URLSearchParams(fd)", null }, - .{ "ups.size", "3" }, - .{ "ups.getAll('a')", "1,2" }, - .{ "ups.getAll('b')", "3" }, - .{ "fd.delete('a')", null }, // the two aren't linked, it created a copy - .{ "ups.size", "3" }, - .{ "ups = new URLSearchParams({over: 9000, spice: 'flow'})", null }, - .{ "ups.size", "2" }, - .{ "ups.getAll('over')", "9000" }, - .{ "ups.getAll('spice')", "flow" }, - }, .{}); +test "Browser: URLSearchParams" { + try testing.htmlRunner("url/url_search_params.html"); } diff --git a/src/tests/storage/local_storage.html b/src/tests/storage/local_storage.html index d4605844..70353007 100644 --- a/src/tests/storage/local_storage.html +++ b/src/tests/storage/local_storage.html @@ -3,10 +3,13 @@ diff --git a/src/tests/url/url.html b/src/tests/url/url.html new file mode 100644 index 00000000..ba574637 --- /dev/null +++ b/src/tests/url/url.html @@ -0,0 +1,77 @@ + + + + + + + + + + diff --git a/src/tests/url/url_search_params.html b/src/tests/url/url_search_params.html new file mode 100644 index 00000000..9bdda17f --- /dev/null +++ b/src/tests/url/url_search_params.html @@ -0,0 +1,93 @@ + + + +