diff options
Diffstat (limited to 'testing/web-platform/tests/background-fetch/fetch.https.window.js')
-rw-r--r-- | testing/web-platform/tests/background-fetch/fetch.https.window.js | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/testing/web-platform/tests/background-fetch/fetch.https.window.js b/testing/web-platform/tests/background-fetch/fetch.https.window.js new file mode 100644 index 0000000000..1756a0e6e3 --- /dev/null +++ b/testing/web-platform/tests/background-fetch/fetch.https.window.js @@ -0,0 +1,280 @@ +// META: script=/common/get-host-info.sub.js +// META: script=/service-workers/service-worker/resources/test-helpers.sub.js +// META: script=resources/utils.js + +'use strict'; + +// Covers basic functionality provided by BackgroundFetchManager.fetch(). +// https://wicg.github.io/background-fetch/#background-fetch-manager-fetch + +const wait = milliseconds => + new Promise(resolve => step_timeout(resolve, milliseconds)); + +promise_test(async test => { + // 6.3.1.9.2: If |registration|’s active worker is null, then reject promise + // with a TypeError and abort these steps. + const script = 'service_workers/sw.js'; + const scope = 'service_workers/' + location.pathname; + + const serviceWorkerRegistration = + await service_worker_unregister_and_register(test, script, scope); + + assert_equals( + serviceWorkerRegistration.active, null, + 'There must not be an activated worker'); + + await promise_rejects_js( + test, TypeError, + serviceWorkerRegistration.backgroundFetch.fetch( + uniqueId(), ['resources/feature-name.txt']), + 'fetch() must reject on pending and installing workers'); + +}, 'Background Fetch requires an activated Service Worker'); + +backgroundFetchTest(async (test, backgroundFetch) => { + // 6.3.1.6: If |requests| is empty, then return a promise rejected with a + // TypeError. + await promise_rejects_js( + test, TypeError, backgroundFetch.fetch(uniqueId(), []), + 'Empty sequences are treated as NULL'); + + // 6.3.1.7.1: Let |internalRequest| be the request of the result of invoking + // the Request constructor with |request|. If this throws an + // exception, return a promise rejected with the exception. + await promise_rejects_js( + test, TypeError, + backgroundFetch.fetch(uniqueId(), 'https://user:pass@domain/secret.txt'), + 'Exceptions thrown in the Request constructor are rethrown'); + + // 6.3.1.7.2: If |internalRequest|’s mode is "no-cors", then return a + // promise rejected with a TypeError. + { + const request = + new Request('resources/feature-name.txt', {mode: 'no-cors'}); + + await promise_rejects_js( + test, TypeError, backgroundFetch.fetch(uniqueId(), request), + 'Requests must not be in no-cors mode'); + } + +}, 'Argument verification is done for BackgroundFetchManager.fetch()'); + +backgroundFetchTest(async (test, backgroundFetch) => { + // 6.3.1.9.2: If |bgFetchMap[id]| exists, reject |promise| with a TypeError + // and abort these steps. + return promise_rejects_js(test, TypeError, Promise.all([ + backgroundFetch.fetch('my-id', 'resources/feature-name.txt?1'), + backgroundFetch.fetch('my-id', 'resources/feature-name.txt?2') + ])); + +}, 'IDs must be unique among active Background Fetch registrations'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, ''); + + assert_equals(registration.id, registrationId); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals('backgroundfetchsuccess', type); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); + +}, 'Empty URL is OK.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, + new Request('https://example/com', { + method: 'PUT', + })); + + assert_equals(registration.id, registrationId); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals(type, 'backgroundfetchsuccess'); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); +}, 'Requests with PUT method require CORS Preflight and succeed.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, + new Request('https://example/com', { + method: 'POST', + headers: {'Content-Type': 'text/json'} + })); + + assert_equals(registration.id, registrationId); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals(type, 'backgroundfetchsuccess'); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); +}, 'Requests with text/json content type require CORS Preflight and succeed.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, 'resources/feature-name.txt'); + + assert_equals(registration.id, registrationId); + assert_equals(registration.uploadTotal, 0); + assert_equals(registration.uploaded, 0); + assert_equals(registration.downloadTotal, 0); + assert_equals(registration.result, ''); + assert_equals(registration.failureReason, ''); + assert_true(registration.recordsAvailable); + // Skip `downloaded`, as the transfer may have started already. + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + assert_equals('backgroundfetchsuccess', type); + assert_equals(results.length, 1); + + assert_equals(eventRegistration.id, registration.id); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); + + assert_true(results[0].url.includes('resources/feature-name.txt')); + assert_equals(results[0].status, 200); + assert_equals(results[0].text, 'Background Fetch'); + +}, 'Using Background Fetch to successfully fetch a single resource'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, 'resources/feature-name.txt'); + + assert_equals(registration.result, ''); + assert_equals(registration.failureReason, ''); + + const {type, eventRegistration, results} = + await getMessageFromServiceWorker(); + assert_equals('backgroundfetchsuccess', type); + + assert_equals(eventRegistration.id, registration.id); + assert_equals(registration.result, 'success'); + assert_equals(registration.failureReason, ''); + +}, 'Registration object gets updated values when a background fetch completes.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + + // Very large download total that will definitely exceed the quota. + const options = {downloadTotal: Number.MAX_SAFE_INTEGER}; + await promise_rejects_dom( + test, 'QUOTA_EXCEEDED_ERR', + backgroundFetch.fetch(registrationId, 'resources/feature-name.txt', options), + 'This fetch should have thrown a quota exceeded error'); + +}, 'Background Fetch that exceeds the quota throws a QuotaExceededError'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registration = await backgroundFetch.fetch( + 'my-id', ['resources/feature-name.txt', 'resources/feature-name.txt']); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + assert_equals('backgroundfetchsuccess', type); + assert_equals(results.length, 2); + + assert_equals(eventRegistration.id, registration.id); + assert_equals(eventRegistration.result, 'success'); + assert_equals(eventRegistration.failureReason, ''); + + for (const result of results) { + assert_true(result.url.includes('resources/feature-name.txt')); + assert_equals(result.status, 200); + assert_equals(result.text, 'Background Fetch'); + } + +}, 'Fetches can have requests with duplicate URLs'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, 'resources/feature-name.txt'); + assert_true(registration.recordsAvailable); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + assert_equals('backgroundfetchsuccess', type); + assert_equals(results.length, 1); + + // Wait for up to 5 seconds for the |eventRegistration|'s recordsAvailable + // flag to be set to false, which happens after the successful invocation + // of the ServiceWorker event has finished. + for (let i = 0; i < 50; ++i) { + if (!registration.recordsAvailable) + break; + await wait(100); + } + + assert_false(registration.recordsAvailable); +}, 'recordsAvailable is false after onbackgroundfetchsuccess finishes execution.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registrationId = uniqueId(); + const registration = + await backgroundFetch.fetch(registrationId, 'resources/missing-cat.txt'); + + assert_equals(registration.id, registrationId); + assert_equals(registration.result, ''); + assert_equals(registration.failureReason, ''); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + assert_equals(type, 'backgroundfetchfail'); + assert_equals(results.length, 1); + assert_true(results[0].url.includes('resources/missing-cat.txt')); + assert_equals(results[0].status, 404); + assert_equals(results[0].text, ''); + + assert_equals(eventRegistration.id, registration.id); + assert_equals(eventRegistration.result, 'failure'); + assert_equals(eventRegistration.failureReason, 'bad-status'); + + assert_equals(registration.result, 'failure'); + assert_equals(registration.failureReason, 'bad-status'); + +}, 'Using Background Fetch to fetch a non-existent resource should fail.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const registration = await backgroundFetch.fetch( + 'my-id', + [location.origin, location.origin.replace('https', 'http')]); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + + assert_equals('backgroundfetchfail', type); + assert_equals(eventRegistration.failureReason, 'fetch-error'); + + assert_equals(results.length, 2); + + const validResponse = results[0] ? results[0] : results[1]; + const nullResponse = !results[0] ? results[0] : results[1]; + + assert_true(validResponse.url.includes(location.origin)); + assert_equals(nullResponse, null); + +}, 'Fetches with mixed content should fail.'); + +backgroundFetchTest(async (test, backgroundFetch) => { + const filePath = '/background-fetch/resources/feature-name.txt'; + const registration = await backgroundFetch.fetch( + uniqueId(), + `https://${get_host_info().REMOTE_HOST}${filePath}`); + + const {type, eventRegistration, results} = await getMessageFromServiceWorker(); + assert_equals(type, 'backgroundfetchfail'); + assert_equals(results.length, 1); + + assert_equals(results[0], null); + assert_equals(eventRegistration.id, registration.id); + assert_equals(eventRegistration.downloaded, 0); +}, 'Responses failing CORS checks are not leaked'); |