mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
Simplify testing
This commit is contained in:
@@ -196,8 +196,7 @@ pub const HTMLAnchorElement = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_href(self: *parser.Anchor, href: []const u8, page: *const Page) !void {
|
pub fn set_href(self: *parser.Anchor, href: []const u8, page: *const Page) !void {
|
||||||
const stitch = @import("../../url.zig").stitch;
|
const full = try urlStitch(page.call_arena, href, page.url.raw, .{});
|
||||||
const full = try stitch(page.call_arena, href, page.url.raw, .{});
|
|
||||||
return try parser.anchorSetHref(self, full);
|
return try parser.anchorSetHref(self, full);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,7 +694,7 @@ pub const HTMLInputElement = struct {
|
|||||||
return try parser.inputGetSrc(self);
|
return try parser.inputGetSrc(self);
|
||||||
}
|
}
|
||||||
pub fn set_src(self: *parser.Input, src: []const u8, page: *Page) !void {
|
pub fn set_src(self: *parser.Input, src: []const u8, page: *Page) !void {
|
||||||
const new_src = try urlStitch(page.call_arena, src, page.url.raw);
|
const new_src = try urlStitch(page.call_arena, src, page.url.raw, .{ .alloc = .if_needed });
|
||||||
try parser.inputSetSrc(self, new_src);
|
try parser.inputSetSrc(self, new_src);
|
||||||
}
|
}
|
||||||
pub fn get_type(self: *parser.Input) ![]const u8 {
|
pub fn get_type(self: *parser.Input) ![]const u8 {
|
||||||
@@ -1266,40 +1265,55 @@ test "Browser.HTML.Element" {
|
|||||||
.{ "a.href", "https://lightpanda.io/opensource-browser/about" },
|
.{ "a.href", "https://lightpanda.io/opensource-browser/about" },
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
test "Browser.HTML.Element.propeties" {
|
test "Browser.HTML.HtmlInputElement.propeties" {
|
||||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io/noslashattheend" });
|
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io/noslashattheend" });
|
||||||
defer runner.deinit();
|
defer runner.deinit();
|
||||||
const bool_valids = [_]Valid{
|
var alloc = std.heap.ArenaAllocator.init(runner.app.allocator);
|
||||||
.{ .input = "true", .is_str = false },
|
defer alloc.deinit();
|
||||||
.{ .input = "", .is_str = true, .expected = "false" },
|
const arena = alloc.allocator();
|
||||||
.{ .input = "13.5", .is_str = true, .expected = "true" },
|
|
||||||
};
|
try runner.testCases(&.{.{ "let elem_input = document.createElement('input')", null }}, .{});
|
||||||
const str_valids = [_]Valid{
|
|
||||||
.{ .input = "foo", .is_str = true },
|
try runner.testCases(&.{.{ "elem_input.form", "null" }}, .{}); // Initial value
|
||||||
.{ .input = "5", .is_str = false, .expected = "5" },
|
// Valid input.form is tested separately :Browser.HTML.HtmlInputElement.propeties.form
|
||||||
.{ .input = "", .is_str = true },
|
try testProperty(arena, &runner, "elem_input.form", "null", &.{.{ .input = "'foo'" }}); // Invalid
|
||||||
.{ .input = "document", .is_str = false, .expected = "[object HTMLDocument]" },
|
|
||||||
};
|
try runner.testCases(&.{.{ "elem_input.accept", "" }}, .{}); // Initial value
|
||||||
// TODO these tests are mostly just data should we store them in Sqlite or so?
|
try testProperty(arena, &runner, "elem_input.accept", null, &str_valids); // Valid
|
||||||
try testCreateElement(&runner, "input");
|
|
||||||
// Valid input.form is tested separately :Browser.HTML.Element.propeties.input.form
|
try runner.testCases(&.{.{ "elem_input.alt", "" }}, .{}); // Initial value
|
||||||
try testProperty(&runner, "input", "form", "null", "null", &.{}, &.{.{ .input = "foo", .is_str = true }});
|
try testProperty(arena, &runner, "elem_input.alt", null, &str_valids); // Valid
|
||||||
try testProperty(&runner, "input", "accept", "", "", &str_valids, &.{});
|
|
||||||
try testProperty(&runner, "input", "alt", "", "", &str_valids, &.{});
|
try runner.testCases(&.{.{ "elem_input.disabled", "false" }}, .{}); // Initial value
|
||||||
try testProperty(&runner, "input", "disabled", "false", "false", &bool_valids, &.{});
|
try testProperty(arena, &runner, "elem_input.disabled", null, &bool_valids); // Valid
|
||||||
try testProperty(&runner, "input", "maxLength", "-1", "0", &.{.{ .input = "5", .is_str = false }}, &.{.{ .input = "banana", .is_str = true }});
|
|
||||||
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.maxLength = -45", null }}, .{}));
|
try runner.testCases(&.{.{ "elem_input.maxLength", "-1" }}, .{}); // Initial value
|
||||||
try testProperty(&runner, "input", "name", "", "", &str_valids, &.{});
|
try testProperty(arena, &runner, "elem_input.maxLength", null, &.{.{ .input = "5" }}); // Valid
|
||||||
try testProperty(&runner, "input", "readOnly", "false", "false", &bool_valids, &.{});
|
try testProperty(arena, &runner, "elem_input.maxLength", "0", &.{.{ .input = "'banana'" }}); // Invalid
|
||||||
try testProperty(&runner, "input", "size", "20", "20", &.{.{ .input = "5", .is_str = false }}, &.{.{ .input = "-26", .is_str = false }});
|
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.maxLength = -45", null }}, .{})); // Error
|
||||||
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.size = 0", null }}, .{}));
|
|
||||||
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.size = 'banana'", null }}, .{}));
|
try runner.testCases(&.{.{ "elem_input.name", "" }}, .{}); // Initial value
|
||||||
try testProperty(&runner, "input", "src", "", "", &.{
|
try testProperty(arena, &runner, "elem_input.name", null, &str_valids); // Valid
|
||||||
.{ .input = "foo", .is_str = true, .expected = "https://lightpanda.io/foo" }, // TODO stitch should work with spaces -> %20
|
|
||||||
.{ .input = "-3", .is_str = false, .expected = "https://lightpanda.io/-3" },
|
try runner.testCases(&.{.{ "elem_input.readOnly", "false" }}, .{}); // Initial value
|
||||||
.{ .input = "", .is_str = true, .expected = "https://lightpanda.io/noslashattheend" },
|
try testProperty(arena, &runner, "elem_input.readOnly", null, &bool_valids); // Valid
|
||||||
}, &.{});
|
|
||||||
try testProperty(&runner, "input", "type", "text", "text", &.{.{ .input = "checkbox", .is_str = true }}, &.{.{ .input = "5", .is_str = true }});
|
try runner.testCases(&.{.{ "elem_input.size", "20" }}, .{}); // Initial value
|
||||||
|
try testProperty(arena, &runner, "elem_input.size", null, &.{.{ .input = "5" }}); // Valid
|
||||||
|
try testProperty(arena, &runner, "elem_input.size", "20", &.{.{ .input = "-26" }}); // Invalid
|
||||||
|
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.size = 0", null }}, .{})); // Error
|
||||||
|
try testing.expectError(error.ExecutionError, runner.testCases(&.{.{ "elem_input.size = 'banana'", null }}, .{})); // Error
|
||||||
|
|
||||||
|
try runner.testCases(&.{.{ "elem_input.src", "" }}, .{}); // Initial value
|
||||||
|
try testProperty(arena, &runner, "elem_input.src", null, &.{
|
||||||
|
.{ .input = "'foo'", .expected = "https://lightpanda.io/foo" }, // TODO stitch should work with spaces -> %20
|
||||||
|
.{ .input = "-3", .expected = "https://lightpanda.io/-3" },
|
||||||
|
.{ .input = "''", .expected = "https://lightpanda.io/noslashattheend" },
|
||||||
|
});
|
||||||
|
|
||||||
|
try runner.testCases(&.{.{ "elem_input.type", "text" }}, .{}); // Initial value
|
||||||
|
try testProperty(arena, &runner, "elem_input.type", null, &.{.{ .input = "'checkbox'", .expected = "checkbox" }}); // Valid
|
||||||
|
try testProperty(arena, &runner, "elem_input.type", "text", &.{.{ .input = "'5'" }}); // Invalid
|
||||||
|
|
||||||
// Properties that are related
|
// Properties that are related
|
||||||
try runner.testCases(&.{
|
try runner.testCases(&.{
|
||||||
@@ -1335,7 +1349,7 @@ test "Browser.HTML.Element.propeties" {
|
|||||||
.{ "input_value.value", "mango" }, // Still mango
|
.{ "input_value.value", "mango" }, // Still mango
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
test "Browser.HTML.Element.propeties.input.form" {
|
test "Browser.HTML.HtmlInputElement.propeties.form" {
|
||||||
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html =
|
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html =
|
||||||
\\ <form action="test.php" target="_blank">
|
\\ <form action="test.php" target="_blank">
|
||||||
\\ <p>
|
\\ <p>
|
||||||
@@ -1348,62 +1362,42 @@ test "Browser.HTML.Element.propeties.input.form" {
|
|||||||
try runner.testCases(&.{
|
try runner.testCases(&.{
|
||||||
.{ "let elem_input = document.querySelector('input')", null },
|
.{ "let elem_input = document.querySelector('input')", null },
|
||||||
}, .{});
|
}, .{});
|
||||||
try testProperty(&runner, "input", "form", "[object HTMLFormElement]", "[object HTMLFormElement]", &.{}, &.{.{ .input = "5", .is_str = false }});
|
try runner.testCases(&.{.{ "elem_input.form", "[object HTMLFormElement]" }}, .{}); // Initial value
|
||||||
|
try runner.testCases(&.{
|
||||||
|
.{ "elem_input.form = 'foo'", null },
|
||||||
|
.{ "elem_input.form", "[object HTMLFormElement]" }, // Invalid
|
||||||
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const Valid = struct {
|
const Check = struct {
|
||||||
input: []const u8,
|
input: []const u8,
|
||||||
is_str: bool,
|
|
||||||
expected: ?[]const u8 = null, // Needed when input != expected
|
expected: ?[]const u8 = null, // Needed when input != expected
|
||||||
};
|
};
|
||||||
const Invalid = struct {
|
const bool_valids = [_]Check{
|
||||||
input: []const u8,
|
.{ .input = "true" },
|
||||||
is_str: bool,
|
.{ .input = "''", .expected = "false" },
|
||||||
|
.{ .input = "13.5", .expected = "true" },
|
||||||
|
};
|
||||||
|
const str_valids = [_]Check{
|
||||||
|
.{ .input = "'foo'", .expected = "foo" },
|
||||||
|
.{ .input = "5", .expected = "5" },
|
||||||
|
.{ .input = "''", .expected = "" },
|
||||||
|
.{ .input = "document", .expected = "[object HTMLDocument]" },
|
||||||
};
|
};
|
||||||
|
|
||||||
fn testCreateElement(runner: *testing.JsRunner, comptime name: []const u8) !void {
|
// .{ "elem.type = '5'", "5" },
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let elem_" ++ name ++ " = document.createElement('" ++ name ++ "')", null },
|
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
// TODO reduce comptime
|
|
||||||
// Default is the expected value after creation and after setting an invalid value
|
|
||||||
// Valid input is expected to return itself or the expected value
|
|
||||||
// Invalid input is expected to return the default value
|
|
||||||
// .{ "elem.type", "text" }, // default
|
|
||||||
// .{ "elem.type = 'checkbox'", "checkbox" }, // valid
|
|
||||||
// .{ "elem.type", "checkbox" },
|
|
||||||
// .{ "elem.type = '5'", "5" }, // invalid
|
|
||||||
// .{ "elem.type", "text" },
|
// .{ "elem.type", "text" },
|
||||||
fn testProperty(
|
fn testProperty(
|
||||||
|
arena: std.mem.Allocator,
|
||||||
runner: *testing.JsRunner,
|
runner: *testing.JsRunner,
|
||||||
comptime name: []const u8,
|
elem_dot_prop: []const u8,
|
||||||
comptime property: []const u8,
|
always: ?[]const u8, // Ignores checks' expected if set
|
||||||
comptime initial: []const u8,
|
checks: []const Check,
|
||||||
comptime default: []const u8,
|
|
||||||
comptime valids: []const Valid,
|
|
||||||
comptime invalids: []const Invalid,
|
|
||||||
) !void {
|
) !void {
|
||||||
const elem_dot_prop = "elem_" ++ name ++ "." ++ property;
|
for (checks) |check| {
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ elem_dot_prop, initial },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
inline for (valids) |valid| {
|
|
||||||
const set_input = if (valid.is_str) "'" ++ valid.input ++ "'" else valid.input;
|
|
||||||
const expected = valid.expected orelse valid.input;
|
|
||||||
try runner.testCases(&.{
|
try runner.testCases(&.{
|
||||||
.{ elem_dot_prop ++ " = " ++ set_input, null },
|
.{ try std.mem.concat(arena, u8, &.{ elem_dot_prop, " = ", check.input }), null },
|
||||||
.{ elem_dot_prop, expected },
|
.{ elem_dot_prop, always orelse check.expected orelse check.input },
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
inline for (invalids) |invalid| {
|
|
||||||
const set_input = if (invalid.is_str) "'" ++ invalid.input ++ "'" else invalid.input;
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ elem_dot_prop ++ " = " ++ set_input, null },
|
|
||||||
.{ elem_dot_prop, default },
|
|
||||||
}, .{});
|
}, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ pub const URL = struct {
|
|||||||
if (opts.alloc == .always) {
|
if (opts.alloc == .always) {
|
||||||
return allocator.dupe(u8, base);
|
return allocator.dupe(u8, base);
|
||||||
}
|
}
|
||||||
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
const protocol_end: usize = blk: {
|
const protocol_end: usize = blk: {
|
||||||
@@ -266,7 +267,7 @@ test "URL: Stitching Base & Src URLs (empty src)" {
|
|||||||
|
|
||||||
const base = "https://www.google.com/xyz/abc/123";
|
const base = "https://www.google.com/xyz/abc/123";
|
||||||
const src = "";
|
const src = "";
|
||||||
const result = try URL.stitch(allocator, src, base);
|
const result = try URL.stitch(allocator, src, base, .{});
|
||||||
defer allocator.free(result);
|
defer allocator.free(result);
|
||||||
try testing.expectString("https://www.google.com/xyz/abc/123", result);
|
try testing.expectString("https://www.google.com/xyz/abc/123", result);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user