|
480 | 480 | });
|
481 | 481 | }, 'FetchEvent#body is a string and is passed to network fallback');
|
482 | 482 |
|
| 483 | +// Test that the request body is sent to network upon network fallback, |
| 484 | +// for a ReadableStream body. |
| 485 | +promise_test(async t => { |
| 486 | + const rs = new ReadableStream({start(c) { |
| 487 | + c.enqueue('i a'); |
| 488 | + c.enqueue('m the request'); |
| 489 | + t.step_timeout(t.step_func(() => { |
| 490 | + c.enqueue(' body'); |
| 491 | + c.close(); |
| 492 | + }, 10)); |
| 493 | + }}); |
| 494 | + // Set page_url to "?ignore" so the service worker falls back to network |
| 495 | + // for the main resource request, and add a suffix to avoid colliding |
| 496 | + // with other tests. |
| 497 | + const page_url = 'resources/?ignore-for-request-body-fallback-string'; |
| 498 | + const frame = await with_iframe(page_url); |
| 499 | + t.add_cleanup(() => { frame.remove(); }); |
| 500 | + // Add "?ignore" so the service worker falls back to echo-content.py. |
| 501 | + const echo_url = '/fetch/api/resources/echo-content.py?ignore'; |
| 502 | + const response = await frame.contentWindow.fetch(echo_url, { |
| 503 | + method: 'POST', |
| 504 | + body: rs |
| 505 | + }); |
| 506 | + const text = await response.text(); |
| 507 | + assert_equals(text, |
| 508 | + 'i am the request body', |
| 509 | + 'the network fallback request should include the request body'); |
| 510 | + }, 'FetchEvent#body is a ReadableStream and is passed to network fallback'); |
| 511 | + |
| 512 | +// Test that the request body is sent to network upon network fallback even when |
| 513 | +// the request body is used in the service worker, for a string body. |
| 514 | +promise_test(async t => { |
| 515 | + // Set page_url to "?ignore" so the service worker falls back to network |
| 516 | + // for the main resource request, and add a suffix to avoid colliding |
| 517 | + // with other tests. |
| 518 | + const page_url = 'resources/?ignore-for-request-body-fallback-string'; |
| 519 | + |
| 520 | + const frame = await with_iframe(page_url); |
| 521 | + t.add_cleanup(() => { frame.remove(); }); |
| 522 | + // Add "?use-and-ignore" so the service worker falls back to echo-content.py. |
| 523 | + const echo_url = '/fetch/api/resources/echo-content.py?use-and-ignore'; |
| 524 | + const response = await frame.contentWindow.fetch(echo_url, { |
| 525 | + method: 'POST', |
| 526 | + body: 'i am the request body' |
| 527 | + }); |
| 528 | + const text = await response.text(); |
| 529 | + assert_equals( |
| 530 | + text, |
| 531 | + 'i am the request body', |
| 532 | + 'the network fallback request should include the request body'); |
| 533 | + }, 'FetchEvent#body is a string, used and passed to network fallback'); |
| 534 | + |
| 535 | +// When the streaming body is used in the service worker, network fallback |
| 536 | +// fails. |
| 537 | +promise_test(async t => { |
| 538 | + const rs = new ReadableStream({start(c) { |
| 539 | + c.enqueue('i a'); |
| 540 | + c.enqueue('m the request'); |
| 541 | + t.step_timeout(t.step_func(() => { |
| 542 | + c.enqueue(' body'); |
| 543 | + c.close(); |
| 544 | + }, 10)); |
| 545 | + }}); |
| 546 | + // Set page_url to "?ignore" so the service worker falls back to network |
| 547 | + // for the main resource request, and add a suffix to avoid colliding |
| 548 | + // with other tests. |
| 549 | + const page_url = 'resources/?ignore-for-request-body-fallback-string'; |
| 550 | + const frame = await with_iframe(page_url); |
| 551 | + t.add_cleanup(() => { frame.remove(); }); |
| 552 | + const echo_url = '/fetch/api/resources/echo-content.py?use-and-ignore'; |
| 553 | + await promise_rejects_js(t, TypeError, frame.contentWindow.fetch(echo_url, { |
| 554 | + method: 'POST', |
| 555 | + body: rs |
| 556 | + }); |
| 557 | + }, 'FetchEvent#body is a ReadableStream, used and passed to network fallback'); |
| 558 | + |
| 559 | +// Test that the request body is sent to network upon network fallback even when |
| 560 | +// the request body is used by clone() in the service worker, for a string body. |
| 561 | +promise_test(async t => { |
| 562 | + // Set page_url to "?ignore" so the service worker falls back to network |
| 563 | + // for the main resource request, and add a suffix to avoid colliding |
| 564 | + // with other tests. |
| 565 | + const page_url = 'resources/?ignore-for-request-body-fallback-string'; |
| 566 | + |
| 567 | + const frame = await with_iframe(page_url); |
| 568 | + t.add_cleanup(() => { frame.remove(); }); |
| 569 | + // Add "?clone-and-ignore" so the service worker falls back to |
| 570 | + // echo-content.py. |
| 571 | + const echo_url = '/fetch/api/resources/echo-content.py?clone-and-ignore'; |
| 572 | + const response = await frame.contentWindow.fetch(echo_url, { |
| 573 | + method: 'POST', |
| 574 | + body: 'i am the request body' |
| 575 | + }); |
| 576 | + const text = await response.text(); |
| 577 | + assert_equals( |
| 578 | + text, |
| 579 | + 'i am the request body', |
| 580 | + 'the network fallback request should include the request body'); |
| 581 | + }, 'FetchEvent#body is a string, cloned and passed to network fallback'); |
| 582 | + |
| 583 | +// When the streaming body is used by clone() in the service worker, network |
| 584 | +// fallback fails. |
| 585 | +promise_test(async t => { |
| 586 | + const rs = new ReadableStream({start(c) { |
| 587 | + c.enqueue('i a'); |
| 588 | + c.enqueue('m the request'); |
| 589 | + t.step_timeout(t.step_func(() => { |
| 590 | + c.enqueue(' body'); |
| 591 | + c.close(); |
| 592 | + }, 10)); |
| 593 | + }}); |
| 594 | + // Set page_url to "?ignore" so the service worker falls back to network |
| 595 | + // for the main resource request, and add a suffix to avoid colliding |
| 596 | + // with other tests. |
| 597 | + const page_url = 'resources/?ignore-for-request-body-fallback-string'; |
| 598 | + const frame = await with_iframe(page_url); |
| 599 | + t.add_cleanup(() => { frame.remove(); }); |
| 600 | + // Add "?clone-and-ignore" so the service worker falls back to |
| 601 | + // echo-content.py. |
| 602 | + const echo_url = '/fetch/api/resources/echo-content.py?clone-and-ignore'; |
| 603 | + const response = await frame.contentWindow.fetch(echo_url, { |
| 604 | + method: 'POST', |
| 605 | + body: 'i am the request body' |
| 606 | + }); |
| 607 | + const text = await response.text(); |
| 608 | + assert_equals( |
| 609 | + text, |
| 610 | + 'i am the request body', |
| 611 | + 'the network fallback request should include the request body'); |
| 612 | + }, 'FetchEvent#body is a ReadableStream, cloned and passed to network fallback'); |
| 613 | + |
483 | 614 | // Test that the service worker can read FetchEvent#body when it is a blob.
|
484 | 615 | // It responds with request body it read.
|
485 | 616 | promise_test(t => {
|
|
851 | 982 | assert_equals(frame.contentDocument.body.textContent,
|
852 | 983 | 'method = POST, isHistoryNavigation = true');
|
853 | 984 | }, 'FetchEvent#request.isHistoryNavigation is true (POST + history.go(-1))');
|
| 985 | + |
| 986 | +// When service worker responds with a Response, no XHR upload progress |
| 987 | +// events are delivered. |
| 988 | +promise_test(async t => { |
| 989 | + const page_url = 'resources/simple.html?ignore-for-request-body-string'; |
| 990 | + const frame = await with_iframe(page_url); |
| 991 | + t.add_cleanup(() => { frame.remove(); }); |
| 992 | + |
| 993 | + const xhr = new frame.contentWindow.XMLHttpRequest(); |
| 994 | + xhr.open('POST', 'simple.html?request-body'); |
| 995 | + xhr.upload.addEventListener('progress', t.unreached_func('progress')); |
| 996 | + xhr.upload.addEventListener('error', t.unreached_func('error')); |
| 997 | + xhr.upload.addEventListener('abort', t.unreached_func('abort')); |
| 998 | + xhr.upload.addEventListener('timeout', t.unreached_func('timeout')); |
| 999 | + xhr.upload.addEventListener('load', t.unreached_func('load')); |
| 1000 | + xhr.upload.addEventListener('loadend', t.unreached_func('loadend')); |
| 1001 | + xhr.send('i am the request body'); |
| 1002 | + |
| 1003 | + await new Promise((resolve) => xhr.addEventListener('load', resolve)); |
| 1004 | + }, 'XHR upload progress events for response coming from SW'); |
| 1005 | + |
| 1006 | +// Upload progress events should be delivered for the network fallback case. |
| 1007 | +promise_test(async t => { |
| 1008 | + const page_url = 'resources/simple.html?ignore-for-request-body-string'; |
| 1009 | + const frame = await with_iframe(page_url); |
| 1010 | + t.add_cleanup(() => { frame.remove(); }); |
| 1011 | + |
| 1012 | + let progress = false; |
| 1013 | + let load = false; |
| 1014 | + let loadend = false; |
| 1015 | + |
| 1016 | + const xhr = new frame.contentWindow.XMLHttpRequest(); |
| 1017 | + xhr.open('POST', '/fetch/api/resources/echo-content.py?ignore'); |
| 1018 | + xhr.upload.addEventListener('progress', () => progress = true); |
| 1019 | + xhr.upload.addEventListener('error', t.unreached_func('error')); |
| 1020 | + xhr.upload.addEventListener('abort', t.unreached_func('abort')); |
| 1021 | + xhr.upload.addEventListener('timeout', t.unreached_func('timeout')); |
| 1022 | + xhr.upload.addEventListener('load', () => load = true); |
| 1023 | + xhr.upload.addEventListener('loadend', () => loadend = true); |
| 1024 | + xhr.send('i am the request body'); |
| 1025 | + |
| 1026 | + await new Promise((resolve) => xhr.addEventListener('load', resolve)); |
| 1027 | + assert_true(progress, 'progress'); |
| 1028 | + assert_true(load, 'load'); |
| 1029 | + assert_true(loadend, 'loadend'); |
| 1030 | + }, 'XHR upload progress events for network fallback'); |
| 1031 | + |
854 | 1032 | </script>
|
855 | 1033 | </body>
|
0 commit comments