summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/background-fetch/fetch.https.window.js
diff options
context:
space:
mode:
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.js280
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');