wrangler 2.0.6 → 2.0.7
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/package.json +5 -3
- package/pages/functions/buildPlugin.ts +13 -0
- package/pages/functions/buildWorker.ts +13 -0
- package/src/__tests__/configuration.test.ts +14 -3
- package/src/__tests__/dev.test.tsx +11 -2
- package/src/__tests__/index.test.ts +25 -10
- package/src/__tests__/init.test.ts +61 -20
- package/src/__tests__/kv.test.ts +8 -8
- package/src/__tests__/pages.test.ts +339 -32
- package/src/__tests__/parse.test.ts +5 -1
- package/src/__tests__/publish.test.ts +184 -69
- package/src/abort.d.ts +3 -0
- package/src/cfetch/index.ts +4 -2
- package/src/cfetch/internal.ts +8 -9
- package/src/config/index.ts +162 -0
- package/src/config/validation.ts +24 -2
- package/src/create-worker-preview.ts +17 -7
- package/src/dev/dev.tsx +5 -4
- package/src/dev/remote.tsx +15 -1
- package/src/durable.ts +102 -0
- package/src/index.tsx +111 -41
- package/src/inspect.ts +39 -0
- package/src/kv.ts +74 -25
- package/src/open-in-browser.ts +5 -12
- package/src/pages.tsx +203 -61
- package/src/parse.ts +21 -4
- package/src/proxy.ts +38 -22
- package/src/publish.ts +18 -93
- package/src/sites.tsx +2 -7
- package/templates/new-worker.ts +16 -1
- package/wrangler-dist/cli.js +32779 -20005
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createFetchResult,
|
|
5
|
+
setMockRawResponse,
|
|
6
|
+
setMockResponse,
|
|
7
|
+
unsetAllMocks,
|
|
8
|
+
} from "./helpers/mock-cfetch";
|
|
4
9
|
import { mockConsoleMethods } from "./helpers/mock-console";
|
|
5
10
|
import { runInTempDir } from "./helpers/run-in-tmp";
|
|
6
11
|
import { runWrangler } from "./helpers/run-wrangler";
|
|
7
|
-
import type { Project,
|
|
8
|
-
import type {
|
|
12
|
+
import type { Deployment, Project, UploadPayloadFile } from "../pages";
|
|
13
|
+
import type { FormData, RequestInit } from "undici";
|
|
14
|
+
|
|
15
|
+
// Asserting within mock responses get swallowed, so run them out-of-band
|
|
16
|
+
const outOfBandTests: (() => void)[] = [];
|
|
17
|
+
function assertLater(fn: () => void) {
|
|
18
|
+
outOfBandTests.push(fn);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function mockGetToken(jwt: string) {
|
|
22
|
+
setMockResponse(
|
|
23
|
+
"/accounts/:accountId/pages/projects/foo/upload-token",
|
|
24
|
+
async ([_url, accountId]) => {
|
|
25
|
+
assertLater(() => {
|
|
26
|
+
expect(accountId).toEqual("some-account-id");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return { jwt };
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
9
33
|
|
|
10
34
|
describe("pages", () => {
|
|
11
35
|
runInTempDir();
|
|
@@ -13,6 +37,12 @@ describe("pages", () => {
|
|
|
13
37
|
function endEventLoop() {
|
|
14
38
|
return new Promise((resolve) => setImmediate(resolve));
|
|
15
39
|
}
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
outOfBandTests.length = 0;
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
outOfBandTests.forEach((fn) => fn());
|
|
45
|
+
});
|
|
16
46
|
|
|
17
47
|
it("should should display a list of available subcommands, for pages with no subcommand", async () => {
|
|
18
48
|
await runWrangler("pages");
|
|
@@ -78,12 +108,16 @@ describe("pages", () => {
|
|
|
78
108
|
"/accounts/:accountId/pages/projects",
|
|
79
109
|
([_url, accountId], init, query) => {
|
|
80
110
|
requests.count++;
|
|
81
|
-
expect(accountId).toEqual("some-account-id");
|
|
82
|
-
expect(query.get("per_page")).toEqual("10");
|
|
83
|
-
expect(query.get("page")).toEqual(`${requests.count}`);
|
|
84
|
-
expect(init).toEqual({});
|
|
85
111
|
const pageSize = Number(query.get("per_page"));
|
|
86
112
|
const page = Number(query.get("page"));
|
|
113
|
+
const expectedPageSize = 10;
|
|
114
|
+
const expectedPage = requests.count;
|
|
115
|
+
assertLater(() => {
|
|
116
|
+
expect(accountId).toEqual("some-account-id");
|
|
117
|
+
expect(pageSize).toEqual(expectedPageSize);
|
|
118
|
+
expect(page).toEqual(expectedPage);
|
|
119
|
+
expect(init).toEqual({});
|
|
120
|
+
});
|
|
87
121
|
return projects.slice((page - 1) * pageSize, page * pageSize);
|
|
88
122
|
}
|
|
89
123
|
);
|
|
@@ -158,12 +192,14 @@ describe("pages", () => {
|
|
|
158
192
|
setMockResponse(
|
|
159
193
|
"/accounts/:accountId/pages/projects",
|
|
160
194
|
([_url, accountId], init) => {
|
|
161
|
-
expect(accountId).toEqual("some-account-id");
|
|
162
|
-
expect(init.method).toEqual("POST");
|
|
163
195
|
const body = JSON.parse(init.body as string);
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
196
|
+
assertLater(() => {
|
|
197
|
+
expect(accountId).toEqual("some-account-id");
|
|
198
|
+
expect(init.method).toEqual("POST");
|
|
199
|
+
expect(body).toEqual({
|
|
200
|
+
name: "a-new-project",
|
|
201
|
+
production_branch: "main",
|
|
202
|
+
});
|
|
167
203
|
});
|
|
168
204
|
return {
|
|
169
205
|
name: "a-new-project",
|
|
@@ -195,8 +231,10 @@ describe("pages", () => {
|
|
|
195
231
|
"/accounts/:accountId/pages/projects/:project/deployments",
|
|
196
232
|
([_url, accountId, project]) => {
|
|
197
233
|
requests.count++;
|
|
198
|
-
|
|
199
|
-
|
|
234
|
+
assertLater(() => {
|
|
235
|
+
expect(project).toEqual("images");
|
|
236
|
+
expect(accountId).toEqual("some-account-id");
|
|
237
|
+
});
|
|
200
238
|
return deployments;
|
|
201
239
|
}
|
|
202
240
|
);
|
|
@@ -279,33 +317,68 @@ describe("pages", () => {
|
|
|
279
317
|
writeFileSync("logo.png", "foobar");
|
|
280
318
|
|
|
281
319
|
setMockResponse(
|
|
282
|
-
"/accounts/:accountId/pages/projects/foo/
|
|
283
|
-
async ([_url, accountId]
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const logoPNGFile = body.get("file") as File;
|
|
288
|
-
expect(await logoPNGFile.text()).toEqual("foobar");
|
|
289
|
-
expect(logoPNGFile.name).toEqual("logo.png");
|
|
320
|
+
"/accounts/:accountId/pages/projects/foo/upload-token",
|
|
321
|
+
async ([_url, accountId]) => {
|
|
322
|
+
assertLater(() => {
|
|
323
|
+
expect(accountId).toEqual("some-account-id");
|
|
324
|
+
});
|
|
290
325
|
|
|
291
326
|
return {
|
|
292
|
-
|
|
327
|
+
jwt: "<<funfetti-auth-jwt>>",
|
|
293
328
|
};
|
|
294
329
|
}
|
|
295
330
|
);
|
|
296
331
|
|
|
332
|
+
setMockResponse(
|
|
333
|
+
"/pages/assets/check-missing",
|
|
334
|
+
"POST",
|
|
335
|
+
async (_, init) => {
|
|
336
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
337
|
+
assertLater(() => {
|
|
338
|
+
expect(init.headers).toMatchObject({
|
|
339
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
340
|
+
});
|
|
341
|
+
expect(body).toMatchObject({
|
|
342
|
+
hashes: ["2082190357cfd3617ccfe04f340c6247"],
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
return body.hashes;
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
350
|
+
assertLater(() => {
|
|
351
|
+
expect(init.headers).toMatchObject({
|
|
352
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
353
|
+
});
|
|
354
|
+
const body = JSON.parse(init.body as string) as UploadPayloadFile[];
|
|
355
|
+
expect(body).toMatchObject([
|
|
356
|
+
{
|
|
357
|
+
key: "2082190357cfd3617ccfe04f340c6247",
|
|
358
|
+
value: Buffer.from("foobar").toString("base64"),
|
|
359
|
+
metadata: {
|
|
360
|
+
contentType: "image/png",
|
|
361
|
+
},
|
|
362
|
+
base64: true,
|
|
363
|
+
},
|
|
364
|
+
]);
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
|
|
297
368
|
setMockResponse(
|
|
298
369
|
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
299
370
|
async ([_url, accountId], init) => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
371
|
+
assertLater(() => {
|
|
372
|
+
expect(accountId).toEqual("some-account-id");
|
|
373
|
+
expect(init.method).toEqual("POST");
|
|
374
|
+
const body = init.body as FormData;
|
|
375
|
+
const manifest = JSON.parse(body.get("manifest") as string);
|
|
376
|
+
expect(manifest).toMatchInlineSnapshot(`
|
|
305
377
|
Object {
|
|
306
378
|
"/logo.png": "2082190357cfd3617ccfe04f340c6247",
|
|
307
379
|
}
|
|
308
380
|
`);
|
|
381
|
+
});
|
|
309
382
|
|
|
310
383
|
return {
|
|
311
384
|
url: "https://abcxyz.foo.pages.dev/",
|
|
@@ -324,17 +397,251 @@ describe("pages", () => {
|
|
|
324
397
|
// `);
|
|
325
398
|
});
|
|
326
399
|
|
|
400
|
+
it("should retry uploads", async () => {
|
|
401
|
+
writeFileSync("logo.txt", "foobar");
|
|
402
|
+
|
|
403
|
+
mockGetToken("<<funfetti-auth-jwt>>");
|
|
404
|
+
|
|
405
|
+
setMockResponse(
|
|
406
|
+
"/pages/assets/check-missing",
|
|
407
|
+
"POST",
|
|
408
|
+
async (_, init) => {
|
|
409
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
410
|
+
assertLater(() => {
|
|
411
|
+
expect(init.headers).toMatchObject({
|
|
412
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
413
|
+
});
|
|
414
|
+
expect(body).toMatchObject({
|
|
415
|
+
hashes: ["1a98fb08af91aca4a7df1764a2c4ddb0"],
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
return body.hashes;
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
// Accumulate multiple requests then assert afterwards
|
|
423
|
+
const requests: RequestInit[] = [];
|
|
424
|
+
setMockRawResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
425
|
+
requests.push(init);
|
|
426
|
+
|
|
427
|
+
if (requests.length < 2) {
|
|
428
|
+
return createFetchResult(null, false, [
|
|
429
|
+
{
|
|
430
|
+
code: 800000,
|
|
431
|
+
message: "Something exploded, please retry",
|
|
432
|
+
},
|
|
433
|
+
]);
|
|
434
|
+
} else {
|
|
435
|
+
return createFetchResult(null, true);
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
setMockResponse(
|
|
440
|
+
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
441
|
+
async ([_url, accountId], init) => {
|
|
442
|
+
assertLater(() => {
|
|
443
|
+
expect(accountId).toEqual("some-account-id");
|
|
444
|
+
expect(init.method).toEqual("POST");
|
|
445
|
+
const body = init.body as FormData;
|
|
446
|
+
const manifest = JSON.parse(body.get("manifest") as string);
|
|
447
|
+
expect(manifest).toMatchInlineSnapshot(`
|
|
448
|
+
Object {
|
|
449
|
+
"/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
450
|
+
}
|
|
451
|
+
`);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
return {
|
|
455
|
+
url: "https://abcxyz.foo.pages.dev/",
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
await runWrangler("pages publish . --project-name=foo");
|
|
461
|
+
|
|
462
|
+
// Assert two identical requests
|
|
463
|
+
expect(requests.length).toBe(2);
|
|
464
|
+
for (const init of requests) {
|
|
465
|
+
assertLater(() => {
|
|
466
|
+
expect(init.headers).toMatchObject({
|
|
467
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
const body = JSON.parse(init.body as string) as UploadPayloadFile[];
|
|
471
|
+
expect(body).toMatchObject([
|
|
472
|
+
{
|
|
473
|
+
key: "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
474
|
+
value: Buffer.from("foobar").toString("base64"),
|
|
475
|
+
metadata: {
|
|
476
|
+
contentType: "text/plain",
|
|
477
|
+
},
|
|
478
|
+
base64: true,
|
|
479
|
+
},
|
|
480
|
+
]);
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
485
|
+
"✨ Success! Uploaded 1 files (TIMINGS)
|
|
486
|
+
|
|
487
|
+
✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
|
|
488
|
+
`);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
it("should try to use multiple buckets (up to the max concurrency)", async () => {
|
|
492
|
+
writeFileSync("logo.txt", "foobar");
|
|
493
|
+
writeFileSync("logo.png", "foobar");
|
|
494
|
+
writeFileSync("logo.html", "foobar");
|
|
495
|
+
writeFileSync("logo.js", "foobar");
|
|
496
|
+
|
|
497
|
+
mockGetToken("<<funfetti-auth-jwt>>");
|
|
498
|
+
|
|
499
|
+
setMockResponse(
|
|
500
|
+
"/pages/assets/check-missing",
|
|
501
|
+
"POST",
|
|
502
|
+
async (_, init) => {
|
|
503
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
504
|
+
assertLater(() => {
|
|
505
|
+
expect(init.headers).toMatchObject({
|
|
506
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
507
|
+
});
|
|
508
|
+
expect(body).toMatchObject({
|
|
509
|
+
hashes: expect.arrayContaining([
|
|
510
|
+
"d96fef225537c9f5e44a3cb27fd0b492",
|
|
511
|
+
"2082190357cfd3617ccfe04f340c6247",
|
|
512
|
+
"6be321bef99e758250dac034474ddbb8",
|
|
513
|
+
"1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
514
|
+
]),
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
return body.hashes;
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
// Accumulate multiple requests then assert afterwards
|
|
522
|
+
const requests: RequestInit[] = [];
|
|
523
|
+
setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
524
|
+
requests.push(init);
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
setMockResponse(
|
|
528
|
+
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
529
|
+
async ([_url, accountId], init) => {
|
|
530
|
+
assertLater(() => {
|
|
531
|
+
expect(accountId).toEqual("some-account-id");
|
|
532
|
+
expect(init.method).toEqual("POST");
|
|
533
|
+
const body = init.body as FormData;
|
|
534
|
+
const manifest = JSON.parse(body.get("manifest") as string);
|
|
535
|
+
expect(manifest).toMatchInlineSnapshot(`
|
|
536
|
+
Object {
|
|
537
|
+
"/logo.html": "d96fef225537c9f5e44a3cb27fd0b492",
|
|
538
|
+
"/logo.js": "6be321bef99e758250dac034474ddbb8",
|
|
539
|
+
"/logo.png": "2082190357cfd3617ccfe04f340c6247",
|
|
540
|
+
"/logo.txt": "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
541
|
+
}
|
|
542
|
+
`);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
url: "https://abcxyz.foo.pages.dev/",
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
await runWrangler("pages publish . --project-name=foo");
|
|
552
|
+
|
|
553
|
+
// We have 3 buckets, so expect 3 uploads
|
|
554
|
+
expect(requests.length).toBe(3);
|
|
555
|
+
const bodies: UploadPayloadFile[][] = [];
|
|
556
|
+
for (const init of requests) {
|
|
557
|
+
expect(init.headers).toMatchObject({
|
|
558
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
559
|
+
});
|
|
560
|
+
bodies.push(JSON.parse(init.body as string) as UploadPayloadFile[]);
|
|
561
|
+
}
|
|
562
|
+
// First bucket should end up with 2 files
|
|
563
|
+
expect(bodies.map((b) => b.length)).toEqual([2, 1, 1]);
|
|
564
|
+
// But we don't know the order, so flatten and test without ordering
|
|
565
|
+
expect(bodies.flatMap((b) => b)).toEqual(
|
|
566
|
+
expect.arrayContaining([
|
|
567
|
+
{
|
|
568
|
+
base64: true,
|
|
569
|
+
key: "d96fef225537c9f5e44a3cb27fd0b492",
|
|
570
|
+
metadata: { contentType: "text/html" },
|
|
571
|
+
value: "Zm9vYmFy",
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
base64: true,
|
|
575
|
+
key: "1a98fb08af91aca4a7df1764a2c4ddb0",
|
|
576
|
+
metadata: { contentType: "text/plain" },
|
|
577
|
+
value: "Zm9vYmFy",
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
base64: true,
|
|
581
|
+
key: "6be321bef99e758250dac034474ddbb8",
|
|
582
|
+
metadata: { contentType: "application/javascript" },
|
|
583
|
+
value: "Zm9vYmFy",
|
|
584
|
+
},
|
|
585
|
+
{
|
|
586
|
+
base64: true,
|
|
587
|
+
key: "2082190357cfd3617ccfe04f340c6247",
|
|
588
|
+
metadata: { contentType: "image/png" },
|
|
589
|
+
value: "Zm9vYmFy",
|
|
590
|
+
},
|
|
591
|
+
])
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
expect(std.out).toMatchInlineSnapshot(`
|
|
595
|
+
"✨ Success! Uploaded 4 files (TIMINGS)
|
|
596
|
+
|
|
597
|
+
✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
|
|
598
|
+
`);
|
|
599
|
+
});
|
|
600
|
+
|
|
327
601
|
it("should not error when directory names contain periods and houses a extensionless file", async () => {
|
|
328
602
|
mkdirSync(".well-known");
|
|
603
|
+
// Note: same content as previous test, but since it's a different extension,
|
|
604
|
+
// it hashes to a different value
|
|
329
605
|
writeFileSync(".well-known/foobar", "foobar");
|
|
330
606
|
|
|
607
|
+
mockGetToken("<<funfetti-auth-jwt>>");
|
|
608
|
+
|
|
331
609
|
setMockResponse(
|
|
332
|
-
"/
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
610
|
+
"/pages/assets/check-missing",
|
|
611
|
+
"POST",
|
|
612
|
+
async (_, init) => {
|
|
613
|
+
const body = JSON.parse(init.body as string) as { hashes: string[] };
|
|
614
|
+
assertLater(() => {
|
|
615
|
+
expect(init.headers).toMatchObject({
|
|
616
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
617
|
+
});
|
|
618
|
+
expect(body).toMatchObject({
|
|
619
|
+
hashes: ["7b764dacfd211bebd8077828a7ddefd7"],
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
return body.hashes;
|
|
623
|
+
}
|
|
336
624
|
);
|
|
337
625
|
|
|
626
|
+
setMockResponse("/pages/assets/upload", "POST", async (_, init) => {
|
|
627
|
+
assertLater(() => {
|
|
628
|
+
expect(init.headers).toMatchObject({
|
|
629
|
+
Authorization: "Bearer <<funfetti-auth-jwt>>",
|
|
630
|
+
});
|
|
631
|
+
const body = JSON.parse(init.body as string) as UploadPayloadFile[];
|
|
632
|
+
expect(body).toMatchObject([
|
|
633
|
+
{
|
|
634
|
+
key: "7b764dacfd211bebd8077828a7ddefd7",
|
|
635
|
+
value: Buffer.from("foobar").toString("base64"),
|
|
636
|
+
metadata: {
|
|
637
|
+
contentType: "application/octet-stream",
|
|
638
|
+
},
|
|
639
|
+
base64: true,
|
|
640
|
+
},
|
|
641
|
+
]);
|
|
642
|
+
});
|
|
643
|
+
});
|
|
644
|
+
|
|
338
645
|
setMockResponse(
|
|
339
646
|
"/accounts/:accountId/pages/projects/foo/deployments",
|
|
340
647
|
async () => ({
|
|
@@ -167,7 +167,11 @@ describe("parseTOML", () => {
|
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
it("should cope with Windows line-endings", () => {
|
|
170
|
-
expect(
|
|
170
|
+
expect(
|
|
171
|
+
parseTOML(
|
|
172
|
+
"# A comment with a Windows line-ending\r\n# Another comment with a Windows line-ending\r\n"
|
|
173
|
+
)
|
|
174
|
+
).toEqual({});
|
|
171
175
|
});
|
|
172
176
|
});
|
|
173
177
|
|