test scaffolding

This commit is contained in:
sjorsdonkers
2025-04-22 16:47:04 +02:00
committed by Sjors
parent 64508cec61
commit d666de07a7
4 changed files with 66 additions and 14 deletions

View File

@@ -58,6 +58,7 @@ pub const Browser = struct {
http_client: *http.Client, http_client: *http.Client,
session_pool: SessionPool, session_pool: SessionPool,
page_arena: std.heap.ArenaAllocator, page_arena: std.heap.ArenaAllocator,
pub const EnvType = Env;
const SessionPool = std.heap.MemoryPool(Session); const SessionPool = std.heap.MemoryPool(Session);

View File

@@ -309,7 +309,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
node_registry: Node.Registry, node_registry: Node.Registry,
node_search_list: Node.Search.List, node_search_list: Node.Search.List,
isolated_world: ?IsolatedWorld, isolated_world: ?IsolatedWorld(CDP_T.Browser.EnvType),
const Self = @This(); const Self = @This();
@@ -481,11 +481,13 @@ pub fn BrowserContext(comptime CDP_T: type) type {
/// An isolated world has it's own instance of globals like Window. /// An isolated world has it's own instance of globals like Window.
/// Generally the client needs to resolve a node into the isolated world to be able to work with it. /// Generally the client needs to resolve a node into the isolated world to be able to work with it.
/// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts. /// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts.
pub const IsolatedWorld = struct { pub fn IsolatedWorld(comptime E: type) type {
name: []const u8, return struct {
grant_universal_access: bool, name: []const u8,
executor: *@import("../browser/env.zig").Env.Executor, grant_universal_access: bool,
}; executor: *E.Executor,
};
}
// This is a generic because when we send a result we have two different // This is a generic because when we send a result we have two different
// behaviors. Normally, we're sending the result to the client. But in some cases // behaviors. Normally, we're sending the result to the client. But in some cases

View File

@@ -39,10 +39,13 @@ pub const Document = @import("../testing.zig").Document;
const Browser = struct { const Browser = struct {
session: ?*Session = null, session: ?*Session = null,
arena: std.heap.ArenaAllocator, arena: std.heap.ArenaAllocator,
env: Env,
pub const EnvType = Env;
pub fn init(app: *App) !Browser { pub fn init(app: *App) !Browser {
return .{ return .{
.arena = std.heap.ArenaAllocator.init(app.allocator), .arena = std.heap.ArenaAllocator.init(app.allocator),
.env = Env{},
}; };
} }
@@ -56,13 +59,14 @@ const Browser = struct {
return error.MockBrowserSessionAlreadyExists; return error.MockBrowserSessionAlreadyExists;
} }
const arena = self.arena.allocator(); const arena = self.arena.allocator();
const executor = arena.create(Executor) catch unreachable; const executor = arena.create(Env.Executor) catch unreachable;
self.session = try arena.create(Session); self.session = try arena.create(Session);
self.session.?.* = .{ self.session.?.* = .{
.page = null, .page = null,
.arena = arena, .arena = self.arena,
.executor = executor, .executor = executor,
.inspector = .{}, .inspector = .{},
.state = 0,
}; };
return self.session.?; return self.session.?;
} }
@@ -77,9 +81,10 @@ const Browser = struct {
const Session = struct { const Session = struct {
page: ?Page = null, page: ?Page = null,
arena: Allocator, arena: std.heap.ArenaAllocator,
executor: *Executor, executor: *Env.Executor,
inspector: Inspector, inspector: Inspector,
state: i32,
pub fn currentPage(self: *Session) ?*Page { pub fn currentPage(self: *Session) ?*Page {
return &(self.page orelse return null); return &(self.page orelse return null);
@@ -92,7 +97,7 @@ const Session = struct {
self.page = .{ self.page = .{
.session = self, .session = self,
.url = URL.parse("https://lightpanda.io/", null) catch unreachable, .url = URL.parse("https://lightpanda.io/", null) catch unreachable,
.aux_data = try self.arena.dupe(u8, aux_data orelse ""), .aux_data = try self.arena.allocator().dupe(u8, aux_data orelse ""),
}; };
return &self.page.?; return &self.page.?;
} }
@@ -107,12 +112,43 @@ const Session = struct {
} }
}; };
const Executor = struct {}; const Env = struct {
pub const Executor = MockExecutor;
pub fn startExecutor(self: *Env, comptime Global: type, state: anytype, module_loader: anytype, kind: anytype) !*Executor {
_ = self;
_ = Global;
_ = state;
_ = module_loader;
_ = kind;
return error.MockExecutor;
}
pub fn stopExecutor(self: *Env, executor: *Executor) void {
_ = self;
_ = executor;
}
};
const MockExecutor = struct {
context: Context,
pub fn startScope(self: *MockExecutor, global: anytype) !void {
_ = self;
_ = global;
}
pub fn endScope(self: *MockExecutor) void {
_ = self;
}
};
const Context = struct {
pub fn debugContextId(self: Context) i32 {
_ = self;
return 0;
}
};
const Inspector = struct { const Inspector = struct {
pub fn getRemoteObject( pub fn getRemoteObject(
self: *const Inspector, self: *const Inspector,
executor: *Executor, executor: *Env.Executor,
group: []const u8, group: []const u8,
value: anytype, value: anytype,
) !RemoteObject { ) !RemoteObject {
@@ -127,6 +163,19 @@ const Inspector = struct {
_ = object_id; _ = object_id;
return try alloc.create(i32); return try alloc.create(i32);
} }
pub fn contextCreated(self: *const Inspector,
executor: *const Env.Executor,
name: []const u8,
origin: []const u8,
aux_data: ?[]const u8,
is_default_context: bool,) void {
_ = self;
_ = executor;
_ = name;
_ = origin;
_ = aux_data;
_ = is_default_context;
}
}; };
const RemoteObject = struct { const RemoteObject = struct {

View File

@@ -43,7 +43,7 @@ pub fn Runner(comptime State: type, comptime Global: type, comptime types: anyty
const G = if (Global == void) DefaultGlobal else Global; const G = if (Global == void) DefaultGlobal else Global;
runner.executor = try runner.env.startExecutor(G, state, runner); runner.executor = try runner.env.startExecutor(G, state, runner, .main);
errdefer runner.env.stopExecutor(runner.executor); errdefer runner.env.stopExecutor(runner.executor);
try runner.executor.startScope(if (Global == void) &default_global else global); try runner.executor.startScope(if (Global == void) &default_global else global);