@fragno-dev/core 0.1.11 → 0.2.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.
- package/.turbo/turbo-build.log +87 -69
- package/CHANGELOG.md +79 -0
- package/dist/api/api.d.ts +21 -2
- package/dist/api/api.d.ts.map +1 -1
- package/dist/api/api.js +2 -1
- package/dist/api/api.js.map +1 -1
- package/dist/api/bind-services.d.ts +0 -1
- package/dist/api/bind-services.d.ts.map +1 -1
- package/dist/api/bind-services.js.map +1 -1
- package/dist/api/error.d.ts.map +1 -1
- package/dist/api/error.js.map +1 -1
- package/dist/api/fragment-definition-builder.d.ts +32 -40
- package/dist/api/fragment-definition-builder.d.ts.map +1 -1
- package/dist/api/fragment-definition-builder.js +15 -21
- package/dist/api/fragment-definition-builder.js.map +1 -1
- package/dist/api/fragment-instantiator.d.ts +51 -30
- package/dist/api/fragment-instantiator.d.ts.map +1 -1
- package/dist/api/fragment-instantiator.js +201 -52
- package/dist/api/fragment-instantiator.js.map +1 -1
- package/dist/api/request-context-storage.d.ts +4 -0
- package/dist/api/request-context-storage.d.ts.map +1 -1
- package/dist/api/request-context-storage.js +6 -0
- package/dist/api/request-context-storage.js.map +1 -1
- package/dist/api/request-input-context.d.ts +57 -1
- package/dist/api/request-input-context.d.ts.map +1 -1
- package/dist/api/request-input-context.js +67 -0
- package/dist/api/request-input-context.js.map +1 -1
- package/dist/api/request-middleware.d.ts +2 -2
- package/dist/api/request-middleware.d.ts.map +1 -1
- package/dist/api/request-middleware.js.map +1 -1
- package/dist/api/request-output-context.d.ts +1 -1
- package/dist/api/request-output-context.d.ts.map +1 -1
- package/dist/api/request-output-context.js.map +1 -1
- package/dist/api/route-caller.d.ts +30 -0
- package/dist/api/route-caller.d.ts.map +1 -0
- package/dist/api/route-caller.js +63 -0
- package/dist/api/route-caller.js.map +1 -0
- package/dist/api/route-handler-input-options.d.ts.map +1 -1
- package/dist/api/route.d.ts +8 -8
- package/dist/api/route.d.ts.map +1 -1
- package/dist/api/route.js.map +1 -1
- package/dist/api/shared-types.d.ts.map +1 -1
- package/dist/client/client-error.d.ts.map +1 -1
- package/dist/client/client-error.js.map +1 -1
- package/dist/client/client.d.ts +90 -50
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +128 -16
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.svelte.d.ts +6 -5
- package/dist/client/client.svelte.d.ts.map +1 -1
- package/dist/client/client.svelte.js +10 -2
- package/dist/client/client.svelte.js.map +1 -1
- package/dist/client/internal/ndjson-streaming.js.map +1 -1
- package/dist/client/react.d.ts +5 -4
- package/dist/client/react.d.ts.map +1 -1
- package/dist/client/react.js +104 -12
- package/dist/client/react.js.map +1 -1
- package/dist/client/solid.d.ts +7 -5
- package/dist/client/solid.d.ts.map +1 -1
- package/dist/client/solid.js +23 -9
- package/dist/client/solid.js.map +1 -1
- package/dist/client/vanilla.d.ts +16 -4
- package/dist/client/vanilla.d.ts.map +1 -1
- package/dist/client/vanilla.js +21 -1
- package/dist/client/vanilla.js.map +1 -1
- package/dist/client/vue.d.ts +10 -4
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +24 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/id.d.ts +2 -0
- package/dist/id.js +3 -0
- package/dist/internal/cuid.d.ts +16 -0
- package/dist/internal/cuid.d.ts.map +1 -0
- package/dist/internal/cuid.js +82 -0
- package/dist/internal/cuid.js.map +1 -0
- package/dist/internal/trace-context.d.ts +23 -0
- package/dist/internal/trace-context.d.ts.map +1 -0
- package/dist/internal/trace-context.js +14 -0
- package/dist/internal/trace-context.js.map +1 -0
- package/dist/mod-client.d.ts +7 -20
- package/dist/mod-client.d.ts.map +1 -1
- package/dist/mod-client.js +25 -13
- package/dist/mod-client.js.map +1 -1
- package/dist/mod.d.ts +8 -6
- package/dist/mod.js +3 -1
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +33 -0
- package/dist/runtime.js.map +1 -0
- package/dist/test/test.d.ts +6 -6
- package/dist/test/test.d.ts.map +1 -1
- package/dist/test/test.js.map +1 -1
- package/dist/util/ssr.js.map +1 -1
- package/package.json +42 -52
- package/src/api/api.test.ts +3 -1
- package/src/api/api.ts +28 -0
- package/src/api/bind-services.ts +0 -5
- package/src/api/error.ts +1 -0
- package/src/api/fragment-definition-builder.extend.test.ts +2 -1
- package/src/api/fragment-definition-builder.test.ts +2 -1
- package/src/api/fragment-definition-builder.ts +56 -112
- package/src/api/fragment-instantiator.test.ts +311 -166
- package/src/api/fragment-instantiator.ts +470 -131
- package/src/api/fragment-services.test.ts +1 -0
- package/src/api/internal/path-runtime.test.ts +8 -0
- package/src/api/internal/path-type.test.ts +3 -1
- package/src/api/internal/route.test.ts +1 -0
- package/src/api/request-context-storage.ts +7 -0
- package/src/api/request-input-context.test.ts +156 -2
- package/src/api/request-input-context.ts +87 -1
- package/src/api/request-middleware.test.ts +43 -2
- package/src/api/request-middleware.ts +4 -3
- package/src/api/request-output-context.test.ts +3 -1
- package/src/api/request-output-context.ts +2 -1
- package/src/api/route-caller.test.ts +195 -0
- package/src/api/route-caller.ts +167 -0
- package/src/api/route-handler-input-options.ts +2 -1
- package/src/api/route.test.ts +4 -2
- package/src/api/route.ts +9 -3
- package/src/api/shared-types.ts +2 -1
- package/src/client/client-builder.test.ts +4 -2
- package/src/client/client-error.test.ts +2 -1
- package/src/client/client-error.ts +1 -1
- package/src/client/client-types.test.ts +19 -5
- package/src/client/client.ssr.test.ts +6 -4
- package/src/client/client.svelte.test.ts +18 -9
- package/src/client/client.svelte.ts +38 -13
- package/src/client/client.test.ts +244 -10
- package/src/client/client.ts +473 -148
- package/src/client/internal/ndjson-streaming.test.ts +6 -3
- package/src/client/internal/ndjson-streaming.ts +1 -0
- package/src/client/react.test.ts +176 -6
- package/src/client/react.ts +226 -31
- package/src/client/solid.test.ts +29 -5
- package/src/client/solid.ts +60 -22
- package/src/client/vanilla.test.ts +148 -6
- package/src/client/vanilla.ts +63 -9
- package/src/client/vue.test.ts +397 -8
- package/src/client/vue.ts +74 -4
- package/src/id.ts +1 -0
- package/src/internal/cuid.test.ts +164 -0
- package/src/internal/cuid.ts +133 -0
- package/src/internal/trace-context.ts +35 -0
- package/src/mod-client.ts +55 -9
- package/src/mod.ts +9 -3
- package/src/runtime.ts +48 -0
- package/src/test/test.test.ts +4 -2
- package/src/test/test.ts +14 -7
- package/src/util/async.test.ts +1 -0
- package/src/util/content-type.test.ts +1 -0
- package/src/util/nanostores.test.ts +3 -1
- package/src/util/ssr.ts +1 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +2 -0
- package/vitest.config.ts +2 -1
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { afterEach, assert, beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { atom, computed, effect } from "nanostores";
|
|
2
4
|
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import { defineFragment } from "../api/fragment-definition-builder";
|
|
7
|
+
import { RequestOutputContext } from "../api/request-output-context";
|
|
3
8
|
import { defineRoute } from "../api/route";
|
|
4
|
-
import { buildUrl, createClientBuilder, getCacheKey, isGetHook, isMutatorHook } from "./client";
|
|
5
|
-
import { useFragno } from "./vanilla";
|
|
6
9
|
import { createAsyncIteratorFromCallback, waitForAsyncIterator } from "../util/async";
|
|
10
|
+
import { buildUrl, createClientBuilder, getCacheKey, isGetHook, isMutatorHook } from "./client";
|
|
7
11
|
import type { FragnoPublicClientConfig } from "./client";
|
|
8
|
-
import { atom, computed, effect } from "nanostores";
|
|
9
|
-
import { defineFragment } from "../api/fragment-definition-builder";
|
|
10
|
-
import { RequestOutputContext } from "../api/request-output-context";
|
|
11
12
|
import { FragnoClientUnknownApiError } from "./client-error";
|
|
13
|
+
import { useFragno } from "./vanilla";
|
|
12
14
|
|
|
13
15
|
// Mock fetch globally
|
|
14
16
|
global.fetch = vi.fn();
|
|
@@ -111,6 +113,59 @@ describe("getCacheKey", () => {
|
|
|
111
113
|
});
|
|
112
114
|
});
|
|
113
115
|
|
|
116
|
+
describe("FormData utilities", () => {
|
|
117
|
+
// These tests verify the internal FormData handling behavior
|
|
118
|
+
|
|
119
|
+
test("prepareRequestBody should JSON-stringify regular objects", () => {
|
|
120
|
+
// We can't test internal functions directly, but we can test through the mutator behavior
|
|
121
|
+
// This is a placeholder to document expected behavior
|
|
122
|
+
const body = { name: "test", value: 123 };
|
|
123
|
+
expect(JSON.stringify(body)).toBe('{"name":"test","value":123}');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("FormData should be detected correctly", () => {
|
|
127
|
+
const formData = new FormData();
|
|
128
|
+
formData.append("file", new Blob(["test"]), "test.txt");
|
|
129
|
+
|
|
130
|
+
expect(formData instanceof FormData).toBe(true);
|
|
131
|
+
expect({} instanceof FormData).toBe(false);
|
|
132
|
+
// Note: null instanceof X is a TS error, so we test with a nullable variable
|
|
133
|
+
const nullValue: unknown = null;
|
|
134
|
+
expect(nullValue instanceof FormData).toBe(false);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("File and Blob should be detected correctly", () => {
|
|
138
|
+
const file = new File(["content"], "test.txt", { type: "text/plain" });
|
|
139
|
+
const blob = new Blob(["content"], { type: "text/plain" });
|
|
140
|
+
|
|
141
|
+
expect(file instanceof File).toBe(true);
|
|
142
|
+
expect(file instanceof Blob).toBe(true);
|
|
143
|
+
expect(blob instanceof Blob).toBe(true);
|
|
144
|
+
expect(blob instanceof File).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("toFormData should convert object with files to FormData", () => {
|
|
148
|
+
const file = new File(["content"], "test.txt", { type: "text/plain" });
|
|
149
|
+
const formData = new FormData();
|
|
150
|
+
formData.append("file", file, file.name);
|
|
151
|
+
formData.append("description", "A test file");
|
|
152
|
+
|
|
153
|
+
expect(formData.get("file")).toBeInstanceOf(File);
|
|
154
|
+
expect(formData.get("description")).toBe("A test file");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("FormData can contain multiple files", () => {
|
|
158
|
+
const file1 = new File(["content1"], "test1.txt", { type: "text/plain" });
|
|
159
|
+
const file2 = new File(["content2"], "test2.txt", { type: "text/plain" });
|
|
160
|
+
const formData = new FormData();
|
|
161
|
+
formData.append("files", file1, file1.name);
|
|
162
|
+
formData.append("files", file2, file2.name);
|
|
163
|
+
|
|
164
|
+
const files = formData.getAll("files");
|
|
165
|
+
expect(files).toHaveLength(2);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
114
169
|
describe("invalidation", () => {
|
|
115
170
|
const testFragment = defineFragment("test-fragment").build();
|
|
116
171
|
const testRoutes = [
|
|
@@ -1271,6 +1326,125 @@ describe("createMutator", () => {
|
|
|
1271
1326
|
|
|
1272
1327
|
expect(result).toBeUndefined();
|
|
1273
1328
|
});
|
|
1329
|
+
|
|
1330
|
+
test("body is optional when inputSchema allows undefined", async () => {
|
|
1331
|
+
const testFragment = defineFragment("test-fragment").build();
|
|
1332
|
+
const testRoutes = [
|
|
1333
|
+
defineRoute({
|
|
1334
|
+
method: "POST",
|
|
1335
|
+
path: "/sign-out",
|
|
1336
|
+
inputSchema: z.object({ sessionId: z.string().optional() }).optional(),
|
|
1337
|
+
outputSchema: z.object({ success: z.boolean() }),
|
|
1338
|
+
handler: async (_ctx, { empty }) => empty(),
|
|
1339
|
+
}),
|
|
1340
|
+
] as const;
|
|
1341
|
+
|
|
1342
|
+
vi.mocked(global.fetch).mockImplementation(async () => {
|
|
1343
|
+
return new Response(null, { status: 204 });
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
const cb = createClientBuilder(testFragment, clientConfig, testRoutes);
|
|
1347
|
+
const signOut = cb.createMutator("POST", "/sign-out");
|
|
1348
|
+
|
|
1349
|
+
const result = await signOut.mutateQuery({});
|
|
1350
|
+
expect(result).toBeUndefined();
|
|
1351
|
+
|
|
1352
|
+
const storeResult = await signOut.mutatorStore.mutate({});
|
|
1353
|
+
expect(storeResult).toBeUndefined();
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1356
|
+
test("should send octet-stream body without wrapping", async () => {
|
|
1357
|
+
const testFragment = defineFragment("test-fragment").build();
|
|
1358
|
+
const testRoutes = [
|
|
1359
|
+
defineRoute({
|
|
1360
|
+
method: "PUT",
|
|
1361
|
+
path: "/upload",
|
|
1362
|
+
contentType: "application/octet-stream",
|
|
1363
|
+
inputSchema: z.unknown(),
|
|
1364
|
+
handler: async (_ctx, { empty }) => empty(),
|
|
1365
|
+
}),
|
|
1366
|
+
] as const;
|
|
1367
|
+
|
|
1368
|
+
vi.mocked(global.fetch).mockImplementation(async () => {
|
|
1369
|
+
return new Response(null, { status: 204 });
|
|
1370
|
+
});
|
|
1371
|
+
|
|
1372
|
+
const cb = createClientBuilder(testFragment, clientConfig, testRoutes);
|
|
1373
|
+
const upload = cb.createMutator("PUT", "/upload");
|
|
1374
|
+
const body = new Uint8Array([1, 2, 3, 4]);
|
|
1375
|
+
|
|
1376
|
+
await upload.mutateQuery({ body });
|
|
1377
|
+
|
|
1378
|
+
const [_url, options] = vi.mocked(global.fetch).mock.calls[0];
|
|
1379
|
+
const headers = options?.headers as Record<string, string> | undefined;
|
|
1380
|
+
|
|
1381
|
+
expect(headers?.["Content-Type"]).toBe("application/octet-stream");
|
|
1382
|
+
expect(options?.body).toBe(body);
|
|
1383
|
+
});
|
|
1384
|
+
|
|
1385
|
+
test("should send ReadableStream body with duplex for octet-stream", async () => {
|
|
1386
|
+
const testFragment = defineFragment("test-fragment").build();
|
|
1387
|
+
const testRoutes = [
|
|
1388
|
+
defineRoute({
|
|
1389
|
+
method: "PUT",
|
|
1390
|
+
path: "/upload",
|
|
1391
|
+
contentType: "application/octet-stream",
|
|
1392
|
+
inputSchema: z.unknown(),
|
|
1393
|
+
handler: async (_ctx, { empty }) => empty(),
|
|
1394
|
+
}),
|
|
1395
|
+
] as const;
|
|
1396
|
+
|
|
1397
|
+
let capturedOptions: (RequestInit & { duplex?: "half" }) | undefined;
|
|
1398
|
+
let capturedBodyText = "";
|
|
1399
|
+
|
|
1400
|
+
vi.mocked(global.fetch).mockImplementation(async (_url, options) => {
|
|
1401
|
+
capturedOptions = options as RequestInit & { duplex?: "half" };
|
|
1402
|
+
const body = capturedOptions?.body;
|
|
1403
|
+
|
|
1404
|
+
if (!(body instanceof ReadableStream)) {
|
|
1405
|
+
throw new Error("Expected ReadableStream body");
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
const reader = body.getReader();
|
|
1409
|
+
const chunks: Uint8Array[] = [];
|
|
1410
|
+
while (true) {
|
|
1411
|
+
const { done, value } = await reader.read();
|
|
1412
|
+
if (done) {
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
if (value) {
|
|
1416
|
+
chunks.push(value);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1421
|
+
const combined = new Uint8Array(totalLength);
|
|
1422
|
+
let offset = 0;
|
|
1423
|
+
for (const chunk of chunks) {
|
|
1424
|
+
combined.set(chunk, offset);
|
|
1425
|
+
offset += chunk.length;
|
|
1426
|
+
}
|
|
1427
|
+
capturedBodyText = new TextDecoder().decode(combined);
|
|
1428
|
+
|
|
1429
|
+
return new Response(null, { status: 204 });
|
|
1430
|
+
});
|
|
1431
|
+
|
|
1432
|
+
const cb = createClientBuilder(testFragment, clientConfig, testRoutes);
|
|
1433
|
+
const upload = cb.createMutator("PUT", "/upload");
|
|
1434
|
+
const body = new ReadableStream<Uint8Array>({
|
|
1435
|
+
start(controller) {
|
|
1436
|
+
controller.enqueue(new TextEncoder().encode("streamed body"));
|
|
1437
|
+
controller.close();
|
|
1438
|
+
},
|
|
1439
|
+
});
|
|
1440
|
+
|
|
1441
|
+
await upload.mutateQuery({ body });
|
|
1442
|
+
|
|
1443
|
+
const headers = capturedOptions?.headers as Record<string, string> | undefined;
|
|
1444
|
+
expect(headers?.["Content-Type"]).toBe("application/octet-stream");
|
|
1445
|
+
expect(capturedOptions?.duplex).toBe("half");
|
|
1446
|
+
expect(capturedBodyText).toBe("streamed body");
|
|
1447
|
+
});
|
|
1274
1448
|
});
|
|
1275
1449
|
|
|
1276
1450
|
describe("createMutator - streaming", () => {
|
|
@@ -1997,6 +2171,55 @@ describe("Custom Fetcher Configuration", () => {
|
|
|
1997
2171
|
expect(url4).toBe("http://localhost:3000/api/test-fragment/users/456?include=posts");
|
|
1998
2172
|
});
|
|
1999
2173
|
|
|
2174
|
+
test("public mountRoute is used for hooks", async () => {
|
|
2175
|
+
let capturedUrl: string | undefined;
|
|
2176
|
+
|
|
2177
|
+
(global.fetch as ReturnType<typeof vi.fn>).mockImplementation(async (url) => {
|
|
2178
|
+
capturedUrl = String(url);
|
|
2179
|
+
return {
|
|
2180
|
+
headers: new Headers(),
|
|
2181
|
+
ok: true,
|
|
2182
|
+
json: async () => [{ id: 1, name: "John" }],
|
|
2183
|
+
} as Response;
|
|
2184
|
+
});
|
|
2185
|
+
|
|
2186
|
+
const client = createClientBuilder(
|
|
2187
|
+
testFragment,
|
|
2188
|
+
{ ...clientConfig, mountRoute: "/api/uploads-direct" },
|
|
2189
|
+
testRoutes,
|
|
2190
|
+
);
|
|
2191
|
+
|
|
2192
|
+
const useUsers = client.createHook("/users");
|
|
2193
|
+
await useUsers.query();
|
|
2194
|
+
|
|
2195
|
+
expect(capturedUrl).toBe("http://localhost:3000/api/uploads-direct/users");
|
|
2196
|
+
});
|
|
2197
|
+
|
|
2198
|
+
test("public mountRoute is used for mutators", async () => {
|
|
2199
|
+
let capturedUrl: string | undefined;
|
|
2200
|
+
|
|
2201
|
+
(global.fetch as ReturnType<typeof vi.fn>).mockImplementation(async (url) => {
|
|
2202
|
+
capturedUrl = String(url);
|
|
2203
|
+
return {
|
|
2204
|
+
headers: new Headers(),
|
|
2205
|
+
ok: true,
|
|
2206
|
+
status: 200,
|
|
2207
|
+
json: async () => ({ id: 2, name: "Jane" }),
|
|
2208
|
+
} as Response;
|
|
2209
|
+
});
|
|
2210
|
+
|
|
2211
|
+
const client = createClientBuilder(
|
|
2212
|
+
testFragment,
|
|
2213
|
+
{ ...clientConfig, mountRoute: "/api/uploads-proxy" },
|
|
2214
|
+
testRoutes,
|
|
2215
|
+
);
|
|
2216
|
+
|
|
2217
|
+
const mutator = client.createMutator("POST", "/users");
|
|
2218
|
+
await mutator.mutateQuery({ body: { name: "Jane" } });
|
|
2219
|
+
|
|
2220
|
+
expect(capturedUrl).toBe("http://localhost:3000/api/uploads-proxy/users");
|
|
2221
|
+
});
|
|
2222
|
+
|
|
2000
2223
|
test("getFetcher returns correct fetcher and options", () => {
|
|
2001
2224
|
const customFetch = vi.fn() as unknown as typeof fetch;
|
|
2002
2225
|
const client = createClientBuilder(
|
|
@@ -2013,7 +2236,7 @@ describe("Custom Fetcher Configuration", () => {
|
|
|
2013
2236
|
expect(defaultOptions).toBeUndefined();
|
|
2014
2237
|
});
|
|
2015
2238
|
|
|
2016
|
-
test("getFetcher returns default fetch and options", () => {
|
|
2239
|
+
test("getFetcher returns a bound default fetch and options", async () => {
|
|
2017
2240
|
const client = createClientBuilder(
|
|
2018
2241
|
testFragment,
|
|
2019
2242
|
{
|
|
@@ -2023,9 +2246,20 @@ describe("Custom Fetcher Configuration", () => {
|
|
|
2023
2246
|
testRoutes,
|
|
2024
2247
|
);
|
|
2025
2248
|
|
|
2026
|
-
const
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2249
|
+
const originalFetch = globalThis.fetch;
|
|
2250
|
+
const fetchSpy = vi.fn<typeof fetch>().mockResolvedValue(new Response(null, { status: 204 }));
|
|
2251
|
+
globalThis.fetch = fetchSpy;
|
|
2252
|
+
|
|
2253
|
+
try {
|
|
2254
|
+
const { fetcher, defaultOptions } = client.getFetcher();
|
|
2255
|
+
expect(fetcher).not.toBe(globalThis.fetch);
|
|
2256
|
+
expect(defaultOptions).toBeDefined();
|
|
2257
|
+
expect(defaultOptions?.credentials).toBe("include");
|
|
2258
|
+
|
|
2259
|
+
await fetcher("https://example.com");
|
|
2260
|
+
expect(fetchSpy).toHaveBeenCalledWith("https://example.com");
|
|
2261
|
+
} finally {
|
|
2262
|
+
globalThis.fetch = originalFetch;
|
|
2263
|
+
}
|
|
2030
2264
|
});
|
|
2031
2265
|
});
|