@@ -196,8 +196,7 @@ pub const HTMLAnchorElement = struct {
196196 }
197197
198198 pub fn set_href (self : * parser.Anchor , href : []const u8 , page : * const Page ) ! void {
199- const stitch = @import ("../../url.zig" ).stitch ;
200- const full = try stitch (page .call_arena , href , page .url .raw , .{});
199+ const full = try urlStitch (page .call_arena , href , page .url .raw , .{});
201200 return try parser .anchorSetHref (self , full );
202201 }
203202
@@ -695,7 +694,7 @@ pub const HTMLInputElement = struct {
695694 return try parser .inputGetSrc (self );
696695 }
697696 pub fn set_src (self : * parser.Input , src : []const u8 , page : * Page ) ! void {
698- const new_src = try urlStitch (page .call_arena , src , page .url .raw );
697+ const new_src = try urlStitch (page .call_arena , src , page .url .raw , .{ . alloc = .if_needed } );
699698 try parser .inputSetSrc (self , new_src );
700699 }
701700 pub fn get_type (self : * parser.Input ) ! []const u8 {
@@ -1266,40 +1265,55 @@ test "Browser.HTML.Element" {
12661265 .{ "a.href" , "https://lightpanda.io/opensource-browser/about" },
12671266 }, .{});
12681267}
1269- test "Browser.HTML.Element .propeties" {
1268+ test "Browser.HTML.HtmlInputElement .propeties" {
12701269 var runner = try testing .jsRunner (testing .tracking_allocator , .{ .url = "https://lightpanda.io/noslashattheend" });
12711270 defer runner .deinit ();
1272- const bool_valids = [_ ]Valid {
1273- .{ .input = "true" , .is_str = false },
1274- .{ .input = "" , .is_str = true , .expected = "false" },
1275- .{ .input = "13.5" , .is_str = true , .expected = "true" },
1276- };
1277- const str_valids = [_ ]Valid {
1278- .{ .input = "foo" , .is_str = true },
1279- .{ .input = "5" , .is_str = false , .expected = "5" },
1280- .{ .input = "" , .is_str = true },
1281- .{ .input = "document" , .is_str = false , .expected = "[object HTMLDocument]" },
1282- };
1283- // TODO these tests are mostly just data should we store them in Sqlite or so?
1284- try testCreateElement (& runner , "input" );
1285- // Valid input.form is tested separately :Browser.HTML.Element.propeties.input.form
1286- try testProperty (& runner , "input" , "form" , "null" , "null" , &.{}, &.{.{ .input = "foo" , .is_str = true }});
1287- try testProperty (& runner , "input" , "accept" , "" , "" , & str_valids , &.{});
1288- try testProperty (& runner , "input" , "alt" , "" , "" , & str_valids , &.{});
1289- try testProperty (& runner , "input" , "disabled" , "false" , "false" , & bool_valids , &.{});
1290- try testProperty (& runner , "input" , "maxLength" , "-1" , "0" , &.{.{ .input = "5" , .is_str = false }}, &.{.{ .input = "banana" , .is_str = true }});
1291- try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.maxLength = -45" , null }}, .{}));
1292- try testProperty (& runner , "input" , "name" , "" , "" , & str_valids , &.{});
1293- try testProperty (& runner , "input" , "readOnly" , "false" , "false" , & bool_valids , &.{});
1294- try testProperty (& runner , "input" , "size" , "20" , "20" , &.{.{ .input = "5" , .is_str = false }}, &.{.{ .input = "-26" , .is_str = false }});
1295- try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.size = 0" , null }}, .{}));
1296- try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.size = 'banana'" , null }}, .{}));
1297- try testProperty (& runner , "input" , "src" , "" , "" , &.{
1298- .{ .input = "foo" , .is_str = true , .expected = "https://lightpanda.io/foo" }, // TODO stitch should work with spaces -> %20
1299- .{ .input = "-3" , .is_str = false , .expected = "https://lightpanda.io/-3" },
1300- .{ .input = "" , .is_str = true , .expected = "https://lightpanda.io/noslashattheend" },
1301- }, &.{});
1302- try testProperty (& runner , "input" , "type" , "text" , "text" , &.{.{ .input = "checkbox" , .is_str = true }}, &.{.{ .input = "5" , .is_str = true }});
1271+ var alloc = std .heap .ArenaAllocator .init (runner .app .allocator );
1272+ defer alloc .deinit ();
1273+ const arena = alloc .allocator ();
1274+
1275+ try runner .testCases (&.{.{ "let elem_input = document.createElement('input')" , null }}, .{});
1276+
1277+ try runner .testCases (&.{.{ "elem_input.form" , "null" }}, .{}); // Initial value
1278+ // Valid input.form is tested separately :Browser.HTML.HtmlInputElement.propeties.form
1279+ try testProperty (arena , & runner , "elem_input.form" , "null" , &.{.{ .input = "'foo'" }}); // Invalid
1280+
1281+ try runner .testCases (&.{.{ "elem_input.accept" , "" }}, .{}); // Initial value
1282+ try testProperty (arena , & runner , "elem_input.accept" , null , & str_valids ); // Valid
1283+
1284+ try runner .testCases (&.{.{ "elem_input.alt" , "" }}, .{}); // Initial value
1285+ try testProperty (arena , & runner , "elem_input.alt" , null , & str_valids ); // Valid
1286+
1287+ try runner .testCases (&.{.{ "elem_input.disabled" , "false" }}, .{}); // Initial value
1288+ try testProperty (arena , & runner , "elem_input.disabled" , null , & bool_valids ); // Valid
1289+
1290+ try runner .testCases (&.{.{ "elem_input.maxLength" , "-1" }}, .{}); // Initial value
1291+ try testProperty (arena , & runner , "elem_input.maxLength" , null , &.{.{ .input = "5" }}); // Valid
1292+ try testProperty (arena , & runner , "elem_input.maxLength" , "0" , &.{.{ .input = "'banana'" }}); // Invalid
1293+ try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.maxLength = -45" , null }}, .{})); // Error
1294+
1295+ try runner .testCases (&.{.{ "elem_input.name" , "" }}, .{}); // Initial value
1296+ try testProperty (arena , & runner , "elem_input.name" , null , & str_valids ); // Valid
1297+
1298+ try runner .testCases (&.{.{ "elem_input.readOnly" , "false" }}, .{}); // Initial value
1299+ try testProperty (arena , & runner , "elem_input.readOnly" , null , & bool_valids ); // Valid
1300+
1301+ try runner .testCases (&.{.{ "elem_input.size" , "20" }}, .{}); // Initial value
1302+ try testProperty (arena , & runner , "elem_input.size" , null , &.{.{ .input = "5" }}); // Valid
1303+ try testProperty (arena , & runner , "elem_input.size" , "20" , &.{.{ .input = "-26" }}); // Invalid
1304+ try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.size = 0" , null }}, .{})); // Error
1305+ try testing .expectError (error .ExecutionError , runner .testCases (&.{.{ "elem_input.size = 'banana'" , null }}, .{})); // Error
1306+
1307+ try runner .testCases (&.{.{ "elem_input.src" , "" }}, .{}); // Initial value
1308+ try testProperty (arena , & runner , "elem_input.src" , null , &.{
1309+ .{ .input = "'foo'" , .expected = "https://lightpanda.io/foo" }, // TODO stitch should work with spaces -> %20
1310+ .{ .input = "-3" , .expected = "https://lightpanda.io/-3" },
1311+ .{ .input = "''" , .expected = "https://lightpanda.io/noslashattheend" },
1312+ });
1313+
1314+ try runner .testCases (&.{.{ "elem_input.type" , "text" }}, .{}); // Initial value
1315+ try testProperty (arena , & runner , "elem_input.type" , null , &.{.{ .input = "'checkbox'" , .expected = "checkbox" }}); // Valid
1316+ try testProperty (arena , & runner , "elem_input.type" , "text" , &.{.{ .input = "'5'" }}); // Invalid
13031317
13041318 // Properties that are related
13051319 try runner .testCases (&.{
@@ -1335,7 +1349,7 @@ test "Browser.HTML.Element.propeties" {
13351349 .{ "input_value.value" , "mango" }, // Still mango
13361350 }, .{});
13371351}
1338- test "Browser.HTML.Element .propeties.input .form" {
1352+ test "Browser.HTML.HtmlInputElement .propeties.form" {
13391353 var runner = try testing .jsRunner (testing .tracking_allocator , .{ .html =
13401354 \\ <form action="test.php" target="_blank">
13411355 \\ <p>
@@ -1348,62 +1362,42 @@ test "Browser.HTML.Element.propeties.input.form" {
13481362 try runner .testCases (&.{
13491363 .{ "let elem_input = document.querySelector('input')" , null },
13501364 }, .{});
1351- try testProperty (& runner , "input" , "form" , "[object HTMLFormElement]" , "[object HTMLFormElement]" , &.{}, &.{.{ .input = "5" , .is_str = false }});
1365+ try runner .testCases (&.{.{ "elem_input.form" , "[object HTMLFormElement]" }}, .{}); // Initial value
1366+ try runner .testCases (&.{
1367+ .{ "elem_input.form = 'foo'" , null },
1368+ .{ "elem_input.form" , "[object HTMLFormElement]" }, // Invalid
1369+ }, .{});
13521370}
13531371
1354- const Valid = struct {
1372+ const Check = struct {
13551373 input : []const u8 ,
1356- is_str : bool ,
13571374 expected : ? []const u8 = null , // Needed when input != expected
13581375};
1359- const Invalid = struct {
1360- input : []const u8 ,
1361- is_str : bool ,
1376+ const bool_valids = [_ ]Check {
1377+ .{ .input = "true" },
1378+ .{ .input = "''" , .expected = "false" },
1379+ .{ .input = "13.5" , .expected = "true" },
1380+ };
1381+ const str_valids = [_ ]Check {
1382+ .{ .input = "'foo'" , .expected = "foo" },
1383+ .{ .input = "5" , .expected = "5" },
1384+ .{ .input = "''" , .expected = "" },
1385+ .{ .input = "document" , .expected = "[object HTMLDocument]" },
13621386};
13631387
1364- fn testCreateElement (runner : * testing.JsRunner , comptime name : []const u8 ) ! void {
1365- try runner .testCases (&.{
1366- .{ "let elem_" ++ name ++ " = document.createElement('" ++ name ++ "')" , null },
1367- }, .{});
1368- }
1369- // TODO reduce comptime
1370- // Default is the expected value after creation and after setting an invalid value
1371- // Valid input is expected to return itself or the expected value
1372- // Invalid input is expected to return the default value
1373- // .{ "elem.type", "text" }, // default
1374- // .{ "elem.type = 'checkbox'", "checkbox" }, // valid
1375- // .{ "elem.type", "checkbox" },
1376- // .{ "elem.type = '5'", "5" }, // invalid
1388+ // .{ "elem.type = '5'", "5" },
13771389// .{ "elem.type", "text" },
13781390fn testProperty (
1391+ arena : std.mem.Allocator ,
13791392 runner : * testing.JsRunner ,
1380- comptime name : []const u8 ,
1381- comptime property : []const u8 ,
1382- comptime initial : []const u8 ,
1383- comptime default : []const u8 ,
1384- comptime valids : []const Valid ,
1385- comptime invalids : []const Invalid ,
1393+ elem_dot_prop : []const u8 ,
1394+ always : ? []const u8 , // Ignores checks' expected if set
1395+ checks : []const Check ,
13861396) ! void {
1387- const elem_dot_prop = "elem_" ++ name ++ "." ++ property ;
1388-
1389- try runner .testCases (&.{
1390- .{ elem_dot_prop , initial },
1391- }, .{});
1392-
1393- inline for (valids ) | valid | {
1394- const set_input = if (valid .is_str ) "'" ++ valid .input ++ "'" else valid .input ;
1395- const expected = valid .expected orelse valid .input ;
1396- try runner .testCases (&.{
1397- .{ elem_dot_prop ++ " = " ++ set_input , null },
1398- .{ elem_dot_prop , expected },
1399- }, .{});
1400- }
1401-
1402- inline for (invalids ) | invalid | {
1403- const set_input = if (invalid .is_str ) "'" ++ invalid .input ++ "'" else invalid .input ;
1397+ for (checks ) | check | {
14041398 try runner .testCases (&.{
1405- .{ elem_dot_prop ++ " = " ++ set_input , null },
1406- .{ elem_dot_prop , default },
1399+ .{ try std . mem . concat ( arena , u8 , &.{ elem_dot_prop , " = " , check . input }) , null },
1400+ .{ elem_dot_prop , always orelse check . expected orelse check . input },
14071401 }, .{});
14081402 }
14091403}
0 commit comments