@ricsam/isolate-fetch 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,482 +0,0 @@
1
- import { test, describe, beforeEach, afterEach } from "node:test";
2
- import assert from "node:assert";
3
- import {
4
- createFetchTestContext,
5
- evalCode,
6
- evalCodeAsync,
7
- runTestCode,
8
- type FetchTestContext,
9
- } from "@ricsam/isolate-test-utils";
10
-
11
- describe("Request", () => {
12
- let ctx: FetchTestContext;
13
-
14
- beforeEach(async () => {
15
- ctx = await createFetchTestContext();
16
- });
17
-
18
- afterEach(() => {
19
- ctx.dispose();
20
- });
21
-
22
- test("text() body method", async () => {
23
- const data = await evalCodeAsync<string>(
24
- ctx.context,
25
- `
26
- (async () => {
27
- const request = new Request("https://example.com", {
28
- method: "POST",
29
- body: "Hello World",
30
- });
31
- const text = await request.text();
32
- return JSON.stringify({ text });
33
- })()
34
- `
35
- );
36
- const result = JSON.parse(data);
37
-
38
- assert.strictEqual(result.text, "Hello World");
39
- });
40
-
41
- test("json() body method", async () => {
42
- const data = await evalCodeAsync<string>(
43
- ctx.context,
44
- `
45
- (async () => {
46
- const request = new Request("https://example.com", {
47
- method: "POST",
48
- body: JSON.stringify({ name: "test", value: 42 }),
49
- });
50
- return JSON.stringify(await request.json());
51
- })()
52
- `
53
- );
54
- const result = JSON.parse(data) as { name: string; value: number };
55
-
56
- assert.strictEqual(result.name, "test");
57
- assert.strictEqual(result.value, 42);
58
- });
59
-
60
- test("arrayBuffer() body method", async () => {
61
- const data = await evalCodeAsync<string>(
62
- ctx.context,
63
- `
64
- (async () => {
65
- const request = new Request("https://example.com", {
66
- method: "POST",
67
- body: "ABC",
68
- });
69
- const buffer = await request.arrayBuffer();
70
- return JSON.stringify({
71
- isArrayBuffer: buffer instanceof ArrayBuffer,
72
- byteLength: buffer.byteLength,
73
- });
74
- })()
75
- `
76
- );
77
- const result = JSON.parse(data) as {
78
- isArrayBuffer: boolean;
79
- byteLength: number;
80
- };
81
-
82
- assert.strictEqual(result.isArrayBuffer, true);
83
- assert.strictEqual(result.byteLength, 3);
84
- });
85
-
86
- test("bodyUsed flag after consumption", async () => {
87
- const data = await evalCodeAsync<string>(
88
- ctx.context,
89
- `
90
- (async () => {
91
- const request = new Request("https://example.com", {
92
- method: "POST",
93
- body: "test",
94
- });
95
- const before = request.bodyUsed;
96
- await request.text();
97
- const after = request.bodyUsed;
98
- return JSON.stringify({ before, after });
99
- })()
100
- `
101
- );
102
- const result = JSON.parse(data) as { before: boolean; after: boolean };
103
-
104
- assert.strictEqual(result.before, false);
105
- assert.strictEqual(result.after, true);
106
- });
107
-
108
- test("body property exists", () => {
109
- const data = evalCode<string>(
110
- ctx.context,
111
- `
112
- const request = new Request("https://example.com", {
113
- method: "POST",
114
- body: "Stream test",
115
- });
116
- JSON.stringify({
117
- hasBody: request.body !== null,
118
- hasBodyUsed: typeof request.bodyUsed === "boolean",
119
- })
120
- `
121
- );
122
- const result = JSON.parse(data) as { hasBody: boolean; hasBodyUsed: boolean };
123
-
124
- assert.strictEqual(result.hasBody, true);
125
- assert.strictEqual(result.hasBodyUsed, true);
126
- });
127
-
128
- test("body property returns HostBackedReadableStream", () => {
129
- const isStream = evalCode<boolean>(
130
- ctx.context,
131
- `
132
- const request = new Request("http://example.com", {
133
- method: "POST",
134
- body: "test body"
135
- });
136
- request.body instanceof HostBackedReadableStream
137
- `
138
- );
139
- assert.strictEqual(isStream, true);
140
- });
141
-
142
- test("can read body via stream reader", async () => {
143
- const result = await evalCodeAsync<string>(
144
- ctx.context,
145
- `
146
- (async () => {
147
- const request = new Request("http://example.com", {
148
- method: "POST",
149
- body: "hello"
150
- });
151
- const reader = request.body.getReader();
152
- const { value, done } = await reader.read();
153
- return JSON.stringify({
154
- hasValue: value != null,
155
- isDone: done
156
- });
157
- })()
158
- `
159
- );
160
- const data = JSON.parse(result) as { hasValue: boolean; isDone: boolean };
161
- assert.strictEqual(data.hasValue, true);
162
- assert.strictEqual(data.isDone, false);
163
- });
164
-
165
- test("Request URL is preserved when created with URL object and init options", () => {
166
- const result = evalCode<string>(
167
- ctx.context,
168
- `
169
- const originalUrl = "http://localhost:3333/auth/get-session";
170
- const request = new Request(originalUrl);
171
- // Create new request with URL object and explicit options (not passing request object)
172
- const newRequest = new Request(new URL(request.url), {
173
- method: request.method,
174
- headers: request.headers,
175
- });
176
- JSON.stringify({
177
- originalUrl: request.url,
178
- newUrl: newRequest.url,
179
- })
180
- `
181
- );
182
- const data = JSON.parse(result) as { originalUrl: string; newUrl: string };
183
- assert.strictEqual(data.originalUrl, "http://localhost:3333/auth/get-session");
184
- assert.strictEqual(data.newUrl, "http://localhost:3333/auth/get-session");
185
- });
186
- });
187
-
188
- /**
189
- * Native Request -> Isolate tests
190
- *
191
- * These tests verify that native Request objects passed into the isolate
192
- * behave identically to Request instances created with `new Request()` in the isolate.
193
- *
194
- * The tests use `runTestCode()` which converts native Request to isolate Request
195
- * instances before executing the test code.
196
- *
197
- * Note: These tests focus on synchronous properties. Body consumption methods
198
- * (text(), json(), arrayBuffer()) require async support in runTestCode which
199
- * is not yet implemented.
200
- */
201
- describe("Native Request -> Isolate", () => {
202
- let ctx: FetchTestContext;
203
-
204
- beforeEach(async () => {
205
- ctx = await createFetchTestContext();
206
- });
207
-
208
- afterEach(() => {
209
- ctx.dispose();
210
- });
211
-
212
- test("native Request should pass instanceof check in isolate", () => {
213
- const runtime = runTestCode(
214
- ctx.context,
215
- `
216
- const request = testingInput.request;
217
- log("instanceof", request instanceof Request);
218
- log("constructorName", request.constructor.name);
219
- `
220
- ).input({
221
- request: new Request("https://example.com/test"),
222
- });
223
-
224
- assert.deepStrictEqual(runtime.logs, {
225
- instanceof: true,
226
- constructorName: "Request",
227
- });
228
- });
229
-
230
- test("url property is preserved", () => {
231
- const runtime = runTestCode(
232
- ctx.context,
233
- `
234
- const request = testingInput.request;
235
- log("url", request.url);
236
- `
237
- ).input({
238
- request: new Request("https://example.com/path?query=value"),
239
- });
240
-
241
- assert.strictEqual(runtime.logs.url, "https://example.com/path?query=value");
242
- });
243
-
244
- test("method property is preserved", () => {
245
- const runtime = runTestCode(
246
- ctx.context,
247
- `
248
- const request = testingInput.request;
249
- log("method", request.method);
250
- `
251
- ).input({
252
- request: new Request("https://example.com", { method: "POST" }),
253
- });
254
-
255
- assert.strictEqual(runtime.logs.method, "POST");
256
- });
257
-
258
- test("headers property is a Headers instance", () => {
259
- const runtime = runTestCode(
260
- ctx.context,
261
- `
262
- const request = testingInput.request;
263
- log("headersInstanceof", request.headers instanceof Headers);
264
- log("contentType", request.headers.get("content-type"));
265
- log("accept", request.headers.get("accept"));
266
- `
267
- ).input({
268
- request: new Request("https://example.com", {
269
- headers: {
270
- "Content-Type": "application/json",
271
- Accept: "text/html",
272
- },
273
- }),
274
- });
275
-
276
- assert.deepStrictEqual(runtime.logs, {
277
- headersInstanceof: true,
278
- contentType: "application/json",
279
- accept: "text/html",
280
- });
281
- });
282
-
283
- test("credentials property is preserved", () => {
284
- const runtime = runTestCode(
285
- ctx.context,
286
- `
287
- const request = testingInput.request;
288
- log("credentials", request.credentials);
289
- `
290
- ).input({
291
- request: new Request("https://example.com", { credentials: "include" }),
292
- });
293
-
294
- assert.strictEqual(runtime.logs.credentials, "include");
295
- });
296
-
297
- test("redirect property is preserved", () => {
298
- const runtime = runTestCode(
299
- ctx.context,
300
- `
301
- const request = testingInput.request;
302
- log("redirect", request.redirect);
303
- `
304
- ).input({
305
- request: new Request("https://example.com", { redirect: "manual" }),
306
- });
307
-
308
- assert.strictEqual(runtime.logs.redirect, "manual");
309
- });
310
-
311
- test("bodyUsed property exists and is false initially", () => {
312
- const runtime = runTestCode(
313
- ctx.context,
314
- `
315
- const request = testingInput.request;
316
- log("bodyUsed", request.bodyUsed);
317
- log("hasBodyUsed", typeof request.bodyUsed === "boolean");
318
- `
319
- ).input({
320
- request: new Request("https://example.com"),
321
- });
322
-
323
- assert.deepStrictEqual(runtime.logs, {
324
- bodyUsed: false,
325
- hasBodyUsed: true,
326
- });
327
- });
328
-
329
- test("all standard properties exist", () => {
330
- const runtime = runTestCode(
331
- ctx.context,
332
- `
333
- const request = testingInput.request;
334
- log("hasUrl", typeof request.url === "string");
335
- log("hasMethod", typeof request.method === "string");
336
- log("hasHeaders", request.headers instanceof Headers);
337
- log("hasMode", typeof request.mode === "string");
338
- log("hasCredentials", typeof request.credentials === "string");
339
- log("hasCache", typeof request.cache === "string");
340
- log("hasRedirect", typeof request.redirect === "string");
341
- log("hasReferrer", typeof request.referrer === "string");
342
- log("hasIntegrity", typeof request.integrity === "string");
343
- `
344
- ).input({
345
- request: new Request("https://example.com"),
346
- });
347
-
348
- assert.deepStrictEqual(runtime.logs, {
349
- hasUrl: true,
350
- hasMethod: true,
351
- hasHeaders: true,
352
- hasMode: true,
353
- hasCredentials: true,
354
- hasCache: true,
355
- hasRedirect: true,
356
- hasReferrer: true,
357
- hasIntegrity: true,
358
- });
359
- });
360
-
361
- describe("Bidirectional Conversion (Native->Isolate->Native)", () => {
362
- test("Request created in isolate should return as native Request", () => {
363
- const runtime = runTestCode(
364
- ctx.context,
365
- `
366
- const request = new Request("https://example.com/test", {
367
- method: "POST",
368
- headers: { "Content-Type": "application/json" }
369
- });
370
- log("request", request);
371
- `
372
- ).input({});
373
-
374
- assert.ok(runtime.logs.request instanceof Request);
375
- assert.strictEqual(
376
- (runtime.logs.request as Request).url,
377
- "https://example.com/test"
378
- );
379
- assert.strictEqual((runtime.logs.request as Request).method, "POST");
380
- });
381
-
382
- test("native Request passed through isolate returns as native Request", () => {
383
- const runtime = runTestCode(
384
- ctx.context,
385
- `
386
- const request = testingInput.request;
387
- log("request", request);
388
- `
389
- ).input({
390
- request: new Request("https://example.com/passthrough", {
391
- method: "PUT",
392
- headers: { "X-Custom": "value" },
393
- }),
394
- });
395
-
396
- assert.ok(runtime.logs.request instanceof Request);
397
- assert.strictEqual(
398
- (runtime.logs.request as Request).url,
399
- "https://example.com/passthrough"
400
- );
401
- assert.strictEqual((runtime.logs.request as Request).method, "PUT");
402
- });
403
-
404
- test("Request headers should be native Headers after round-trip", () => {
405
- const runtime = runTestCode(
406
- ctx.context,
407
- `
408
- const request = new Request("https://example.com", {
409
- headers: { "Content-Type": "application/json" }
410
- });
411
- log("request", request);
412
- `
413
- ).input({});
414
-
415
- assert.ok(runtime.logs.request instanceof Request);
416
- assert.ok((runtime.logs.request as Request).headers instanceof Headers);
417
- assert.strictEqual(
418
- (runtime.logs.request as Request).headers.get("content-type"),
419
- "application/json"
420
- );
421
- });
422
-
423
- test("nested object with Request converts properly", () => {
424
- const runtime = runTestCode(
425
- ctx.context,
426
- `
427
- const request = testingInput.request;
428
- log("result", {
429
- request: request,
430
- metadata: { id: 123 }
431
- });
432
- `
433
- ).input({
434
- request: new Request("https://example.com", { method: "DELETE" }),
435
- });
436
-
437
- const result = runtime.logs.result as {
438
- request: Request;
439
- metadata: { id: number };
440
- };
441
- assert.ok(result.request instanceof Request);
442
- assert.strictEqual(result.request.method, "DELETE");
443
- assert.deepStrictEqual(result.metadata, { id: 123 });
444
- });
445
-
446
- test("Request with modified headers converts properly through round-trip", () => {
447
- const runtime = runTestCode(
448
- ctx.context,
449
- `
450
- const headers = new Headers(testingInput.request.headers);
451
- headers.append("test2", "test2");
452
- headers.delete("to-remove");
453
- const request = new Request(new URL(testingInput.request.url), {
454
- method: testingInput.request.method,
455
- headers: headers,
456
- });
457
- log("result", {
458
- request: request,
459
- metadata: { id: 123 }
460
- });
461
- `
462
- ).input({
463
- request: new Request("https://example.com", {
464
- method: "DELETE",
465
- headers: { test: "test", "to-remove": "to-remove" },
466
- }),
467
- });
468
-
469
- const result = runtime.logs.result as {
470
- request: Request;
471
- metadata: { id: number };
472
- };
473
- assert.ok(result.request instanceof Request);
474
- assert.strictEqual(result.request.method, "DELETE");
475
- assert.deepStrictEqual(result.metadata, { id: 123 });
476
- assert.ok(result.request.headers instanceof Headers);
477
- assert.strictEqual(result.request.headers.get("test"), "test");
478
- assert.strictEqual(result.request.headers.get("test2"), "test2");
479
- assert.strictEqual(result.request.headers.has("to-remove"), false);
480
- });
481
- });
482
- });