Skip to content

Commit 8446a60

Browse files
committed
migrate fetch tests to htmlRunner
1 parent c5520be commit 8446a60

File tree

7 files changed

+219
-115
lines changed

7 files changed

+219
-115
lines changed

src/browser/fetch/Headers.zig

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

1919
const std = @import("std");
20+
const log = @import("../../log.zig");
2021
const URL = @import("../../url.zig").URL;
2122
const Page = @import("../page.zig").Page;
2223

24+
const iterator = @import("../iterator/iterator.zig");
25+
2326
const v8 = @import("v8");
2427
const Env = @import("../env.zig").Env;
2528

@@ -108,7 +111,8 @@ pub fn constructor(_init: ?HeadersInit, page: *Page) !Headers {
108111
}
109112

110113
pub fn append(self: *Headers, name: []const u8, value: []const u8, allocator: std.mem.Allocator) !void {
111-
const gop = try self.headers.getOrPut(allocator, name);
114+
const key = try allocator.dupe(u8, name);
115+
const gop = try self.headers.getOrPut(allocator, key);
112116

113117
if (gop.found_existing) {
114118
// If we found it, append the value.
@@ -129,13 +133,13 @@ pub fn _delete(self: *Headers, name: []const u8) void {
129133
_ = self.headers.remove(name);
130134
}
131135

132-
pub const HeaderEntryIterator = struct {
136+
pub const HeadersEntryIterator = struct {
133137
slot: [2][]const u8,
134138
iter: HeaderHashMap.Iterator,
135139

136140
// TODO: these SHOULD be in lexigraphical order but I'm not sure how actually
137141
// important that is.
138-
pub fn _next(self: *HeaderEntryIterator) ?[2][]const u8 {
142+
pub fn _next(self: *HeadersEntryIterator) ?[2][]const u8 {
139143
if (self.iter.next()) |entry| {
140144
self.slot[0] = entry.key_ptr.*;
141145
self.slot[1] = entry.value_ptr.*;
@@ -146,10 +150,12 @@ pub const HeaderEntryIterator = struct {
146150
}
147151
};
148152

149-
pub fn _entries(self: *const Headers) HeaderEntryIterator {
153+
pub fn _entries(self: *const Headers) HeadersEntryIterable {
150154
return .{
151-
.slot = undefined,
152-
.iter = self.headers.iterator(),
155+
.inner = .{
156+
.slot = undefined,
157+
.iter = self.headers.iterator(),
158+
},
153159
};
154160
}
155161

@@ -171,10 +177,10 @@ pub fn _has(self: *const Headers, name: []const u8) bool {
171177
return self.headers.contains(name);
172178
}
173179

174-
pub const HeaderKeyIterator = struct {
180+
pub const HeadersKeyIterator = struct {
175181
iter: HeaderHashMap.KeyIterator,
176182

177-
pub fn _next(self: *HeaderKeyIterator) ?[]const u8 {
183+
pub fn _next(self: *HeadersKeyIterator) ?[]const u8 {
178184
if (self.iter.next()) |key| {
179185
return key.*;
180186
} else {
@@ -183,21 +189,22 @@ pub const HeaderKeyIterator = struct {
183189
}
184190
};
185191

186-
pub fn _keys(self: *const Headers) HeaderKeyIterator {
187-
return .{ .iter = self.headers.keyIterator() };
192+
pub fn _keys(self: *const Headers) HeadersKeyIterable {
193+
return .{ .inner = .{ .iter = self.headers.keyIterator() } };
188194
}
189195

190196
pub fn _set(self: *Headers, name: []const u8, value: []const u8, page: *Page) !void {
191197
const arena = page.arena;
192198

193-
const gop = try self.headers.getOrPut(arena, name);
199+
const key = try arena.dupe(u8, name);
200+
const gop = try self.headers.getOrPut(arena, key);
194201
gop.value_ptr.* = try arena.dupe(u8, value);
195202
}
196203

197-
pub const HeaderValueIterator = struct {
204+
pub const HeadersValueIterator = struct {
198205
iter: HeaderHashMap.ValueIterator,
199206

200-
pub fn _next(self: *HeaderValueIterator) ?[]const u8 {
207+
pub fn _next(self: *HeadersValueIterator) ?[]const u8 {
201208
if (self.iter.next()) |value| {
202209
return value.*;
203210
} else {
@@ -206,53 +213,15 @@ pub const HeaderValueIterator = struct {
206213
}
207214
};
208215

209-
pub fn _values(self: *const Headers) HeaderValueIterator {
210-
return .{ .iter = self.headers.valueIterator() };
216+
pub fn _values(self: *const Headers) HeadersValueIterable {
217+
return .{ .inner = .{ .iter = self.headers.valueIterator() } };
211218
}
212219

220+
pub const HeadersKeyIterable = iterator.Iterable(HeadersKeyIterator, "HeadersKeyIterator");
221+
pub const HeadersValueIterable = iterator.Iterable(HeadersValueIterator, "HeadersValueIterator");
222+
pub const HeadersEntryIterable = iterator.Iterable(HeadersEntryIterator, "HeadersEntryIterator");
223+
213224
const testing = @import("../../testing.zig");
214-
test "fetch: headers" {
215-
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io" });
216-
defer runner.deinit();
217-
218-
try runner.testCases(&.{
219-
.{ "let emptyHeaders = new Headers()", "undefined" },
220-
}, .{});
221-
222-
try runner.testCases(&.{
223-
.{ "let headers = new Headers({'Set-Cookie': 'name=world'})", "undefined" },
224-
.{ "headers.get('set-cookie')", "name=world" },
225-
}, .{});
226-
227-
// adapted from the mdn examples
228-
try runner.testCases(&.{
229-
.{ "const myHeaders = new Headers();", "undefined" },
230-
.{ "myHeaders.append('Content-Type', 'image/jpeg')", "undefined" },
231-
.{ "myHeaders.has('Picture-Type')", "false" },
232-
.{ "myHeaders.get('Content-Type')", "image/jpeg" },
233-
.{ "myHeaders.append('Content-Type', 'image/png')", "undefined" },
234-
.{ "myHeaders.get('Content-Type')", "image/jpeg, image/png" },
235-
.{ "myHeaders.delete('Content-Type')", "undefined" },
236-
.{ "myHeaders.get('Content-Type')", "null" },
237-
.{ "myHeaders.set('Picture-Type', 'image/svg')", "undefined" },
238-
.{ "myHeaders.get('Picture-Type')", "image/svg" },
239-
.{ "myHeaders.has('Picture-Type')", "true" },
240-
}, .{});
241-
242-
try runner.testCases(&.{
243-
.{ "const originalHeaders = new Headers([['Content-Type', 'application/json'], ['Authorization', 'Bearer token123']])", "undefined" },
244-
.{ "originalHeaders.get('Content-Type')", "application/json" },
245-
.{ "originalHeaders.get('Authorization')", "Bearer token123" },
246-
.{ "const newHeaders = new Headers(originalHeaders)", "undefined" },
247-
.{ "newHeaders.get('Content-Type')", "application/json" },
248-
.{ "newHeaders.get('Authorization')", "Bearer token123" },
249-
.{ "newHeaders.has('Content-Type')", "true" },
250-
.{ "newHeaders.has('Authorization')", "true" },
251-
.{ "newHeaders.has('X-Custom')", "false" },
252-
// Verify that modifying the new headers doesn't affect the original
253-
.{ "newHeaders.set('X-Custom', 'test-value')", "undefined" },
254-
.{ "newHeaders.get('X-Custom')", "test-value" },
255-
.{ "originalHeaders.get('X-Custom')", "null" },
256-
.{ "originalHeaders.has('X-Custom')", "false" },
257-
}, .{});
225+
test "fetch: Headers" {
226+
try testing.htmlRunner("fetch/headers.html");
258227
}

src/browser/fetch/Request.zig

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ pub const RequestCache = enum {
5454
return null;
5555
}
5656
}
57+
58+
pub fn toString(self: RequestCache) []const u8 {
59+
return @tagName(self);
60+
}
5761
};
5862

5963
pub const RequestCredentials = enum {
@@ -70,6 +74,10 @@ pub const RequestCredentials = enum {
7074
return null;
7175
}
7276
}
77+
78+
pub fn toString(self: RequestCredentials) []const u8 {
79+
return @tagName(self);
80+
}
7381
};
7482

7583
// https://developer.mozilla.org/en-US/docs/Web/API/RequestInit
@@ -154,6 +162,10 @@ pub fn get_cache(self: *const Request) RequestCache {
154162
return self.cache;
155163
}
156164

165+
pub fn get_credentials(self: *const Request) RequestCredentials {
166+
return self.credentials;
167+
}
168+
157169
pub fn get_headers(self: *Request) *Headers {
158170
return &self.headers;
159171
}
@@ -249,50 +261,6 @@ pub fn _text(self: *Response, page: *Page) !Env.Promise {
249261
}
250262

251263
const testing = @import("../../testing.zig");
252-
test "fetch: request" {
253-
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io" });
254-
defer runner.deinit();
255-
256-
try runner.testCases(&.{
257-
.{ "let request = new Request('flower.png')", "undefined" },
258-
.{ "request.url", "https://lightpanda.io/flower.png" },
259-
.{ "request.method", "GET" },
260-
}, .{});
261-
262-
try runner.testCases(&.{
263-
.{ "let request2 = new Request('https://google.com', { method: 'POST', body: 'Hello, World' })", "undefined" },
264-
.{ "request2.url", "https://google.com" },
265-
.{ "request2.method", "POST" },
266-
}, .{});
267-
}
268-
269-
test "fetch: Browser.fetch" {
270-
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
271-
defer runner.deinit();
272-
273-
try runner.testCases(&.{
274-
.{
275-
\\ var ok = false;
276-
\\ const request = new Request("http://127.0.0.1:9582/loader");
277-
\\ fetch(request).then((response) => { ok = response.ok; });
278-
\\ false;
279-
,
280-
"false",
281-
},
282-
// all events have been resolved.
283-
.{ "ok", "true" },
284-
}, .{});
285-
286-
try runner.testCases(&.{
287-
.{
288-
\\ var ok2 = false;
289-
\\ const request2 = new Request("http://127.0.0.1:9582/loader");
290-
\\ (async function () { resp = await fetch(request2); ok2 = resp.ok; }());
291-
\\ false;
292-
,
293-
"false",
294-
},
295-
// all events have been resolved.
296-
.{ "ok2", "true" },
297-
}, .{});
264+
test "fetch: Request" {
265+
try testing.htmlRunner("fetch/request.html");
298266
}

src/browser/fetch/Response.zig

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ const Page = @import("../page.zig").Page;
3636
// https://developer.mozilla.org/en-US/docs/Web/API/Response
3737
const Response = @This();
3838

39-
status: u16 = 0,
39+
status: u16 = 200,
40+
status_text: []const u8 = "",
4041
headers: Headers,
4142
mime: ?Mime = null,
4243
url: []const u8 = "",
@@ -50,7 +51,7 @@ const ResponseBody = union(enum) {
5051

5152
const ResponseOptions = struct {
5253
status: u16 = 200,
53-
statusText: []const u8 = "",
54+
statusText: ?[]const u8 = null,
5455
headers: ?HeadersInit = null,
5556
};
5657

@@ -72,10 +73,13 @@ pub fn constructor(_input: ?ResponseBody, _options: ?ResponseOptions, page: *Pag
7273
};
7374

7475
const headers: Headers = if (options.headers) |hdrs| try Headers.constructor(hdrs, page) else .{};
76+
const status_text = if (options.statusText) |st| try arena.dupe(u8, st) else "";
7577

7678
return .{
7779
.body = body,
7880
.headers = headers,
81+
.status = options.status,
82+
.status_text = status_text,
7983
};
8084
}
8185

@@ -105,6 +109,10 @@ pub fn get_status(self: *const Response) u16 {
105109
return self.status;
106110
}
107111

112+
pub fn get_statusText(self: *const Response) []const u8 {
113+
return self.status_text;
114+
}
115+
108116
pub fn get_url(self: *const Response) []const u8 {
109117
return self.url;
110118
}
@@ -183,9 +191,6 @@ pub fn _text(self: *Response, page: *Page) !Env.Promise {
183191
}
184192

185193
const testing = @import("../../testing.zig");
186-
test "fetch: response" {
187-
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .url = "https://lightpanda.io" });
188-
defer runner.deinit();
189-
190-
try runner.testCases(&.{}, .{});
194+
test "fetch: Response" {
195+
try testing.htmlRunner("fetch/response.html");
191196
}

src/browser/fetch/fetch.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ const Response = @import("Response.zig");
3636

3737
pub const Interfaces = .{
3838
@import("Headers.zig"),
39-
@import("Headers.zig").HeaderEntryIterator,
40-
@import("Headers.zig").HeaderKeyIterator,
41-
@import("Headers.zig").HeaderValueIterator,
39+
@import("Headers.zig").HeadersEntryIterable,
40+
@import("Headers.zig").HeadersKeyIterable,
41+
@import("Headers.zig").HeadersValueIterable,
4242
@import("Request.zig"),
4343
@import("Response.zig"),
4444
};

0 commit comments

Comments
 (0)