testing/web-platform/mozilla/tests/service-workers/service-worker/fetch-event.https.html
author Ehsan Akhgari <ehsan@mozilla.com>
Tue, 01 Mar 2016 17:34:31 -0500
changeset 288104 c74866f52320fd314ae8c098d6eaae880c856e96
parent 287588 dd3a0551e7b16f255de1c7ccc41717f3fc0e211f
child 288147 60633fe1415f9ac2f8a417c123eaef877d4bc67e
permissions -rw-r--r--
Bug 1120715 - Part 4: Add tests for Request.cache; r=bkelly

<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/get-host-info.sub.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
var worker = 'resources/fetch-event-test-worker.js';

async_test(function(t) {
    var scope = 'resources/simple.html?string';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(
            frame.contentDocument.body.textContent,
            'Test string',
            'Service Worker should respond to fetch with a test string');
          assert_equals(
            frame.contentDocument.contentType,
            'text/plain',
            'The content type of the response created with a string should be text/plain');
          assert_equals(
            frame.contentDocument.characterSet,
            'UTF-8',
            'The character set of the response created with a string should be UTF-8');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with string');

async_test(function(t) {
    var scope = 'resources/simple.html?blob';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(
            frame.contentDocument.body.textContent,
            'Test blob',
            'Service Worker should respond to fetch with a test string');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with blob body');

async_test(function(t) {
    var scope = 'resources/simple.html?referrer';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(
            frame.contentDocument.body.textContent,
            'Referrer: ' + document.location.href,
            'Service Worker should respond to fetch with the referrer URL');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with the referrer URL');

function run_referrer_policy_tests(frame, referrer, href, origin) {
    return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                     {method: "GET", referrer: referrer})
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + href + '\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url,
                                           {method: "GET", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: about:client\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with no referrer when a member of RequestInit is present with an HTTP request');
          return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                           {referrerPolicy: "", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + href + '\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with the referrer with ""');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url,
                                           {referrerPolicy: "", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: about:client\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with no referrer with ""');
          return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                           {referrerPolicy: "origin-only", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + origin + '\n' +
            'ReferrerPolicy: origin-only',
            'Service Worker should respond to fetch with the referrer origin with "origin-only" and a same origin request');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url,
                                           {referrerPolicy: "origin-only", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + origin + '\n' +
            'ReferrerPolicy: origin-only',
            'Service Worker should respond to fetch with the referrer origin with "origin-only" and a cross origin request');
          return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                           {referrerPolicy: "origin-when-cross-origin", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + href + '\n' +
            'ReferrerPolicy: origin-when-cross-origin',
            'Service Worker should respond to fetch with the referrer URL with "origin-when-cross-origin" and a same origin request');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url,
                                           {referrerPolicy: "origin-when-cross-origin", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + origin + '\n' +
            'ReferrerPolicy: origin-when-cross-origin',
            'Service Worker should respond to fetch with the referrer origin with "origin-when-cross-origin" and a cross origin request');
          return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                           {referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + href + '\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and a same origin request');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url,
                                           {referrerPolicy: "no-referrer-when-downgrade", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: about:client\n' +
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and an HTTP request');
          var http_url = get_host_info()['HTTP_ORIGIN'] + base_path() +
                         '/resources/simple.html?referrerFull';
          return frame.contentWindow.fetch(http_url, {referrerPolicy: "unsafe-url", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: ' + href + '\n' +
            'ReferrerPolicy: unsafe-url',
            'Service Worker should respond to fetch with no referrer with "unsafe-url"');
          return frame.contentWindow.fetch('resources/simple.html?referrerFull',
                                           {referrerPolicy: "no-referrer", referrer: referrer});
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          assert_equals(
            response_text,
            'Referrer: about:client\n' +
            'ReferrerPolicy: no-referrer',
            'Service Worker should respond to fetch with no referrer URL with "no-referrer"');
        });
}

async_test(function(t) {
    var scope = 'resources/simple.html?referrerPolicy';
    var frame;
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(f) {
          frame = f;
          assert_equals(
            frame.contentDocument.body.textContent,
            'ReferrerPolicy: no-referrer-when-downgrade',
            'Service Worker should respond to fetch with the default referrer policy');
          // First, run the referrer policy tests without passing a referrer in RequestInit.
          return run_referrer_policy_tests(frame, undefined, frame.contentDocument.location.href,
                                           frame.contentDocument.location.origin);
        })
      .then(function() {
          // Now, run the referrer policy tests while passing a referrer in RequestInit.
          var referrer = get_host_info()['HTTPS_ORIGIN'] + base_path() + 'fake-referrer';
          return run_referrer_policy_tests(frame, 'fake-referrer', referrer,
                                           frame.contentDocument.location.origin);
        })
      .then(function() {
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with the referrer URL');

async_test(function(t) {
    var scope = 'resources/simple.html?clientId';
    var frame;
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(f) {
          frame = f;
          assert_equals(
            frame.contentDocument.body.textContent,
            'Client ID Not Found',
            'Service Worker should respond to fetch with a client id');
          return frame.contentWindow.fetch('resources/other.html?clientId');
        })
      .then(function(response) { return response.text(); })
      .then(function(response_text) {
          var new_client_id = response_text.substr(17);
          assert_equals(
            response_text.substr(0, 15),
            'Client ID Found',
            'Service Worker should respond to fetch with an existing client id');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with an existing client id');

async_test(function(t) {
    var scope = 'resources/simple.html?ignore';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(frame.contentDocument.body.textContent,
                        'Here\'s a simple html file.\n',
                        'Response should come from fallback to native fetch');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker does not respond to fetch event');

async_test(function(t) {
    var scope = 'resources/simple.html?null';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(frame.contentDocument.body.textContent,
                        '',
                        'Response should be the empty string');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with null response body');

async_test(function(t) {
    var scope = 'resources/simple.html?fetch';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(frame.contentDocument.body.textContent,
                        'Here\'s an other html file.\n',
                        'Response should come from fetched other file');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker fetches other file in fetch event');

async_test(function(t) {
    var scope = 'resources/simple.html?form-post';
    var frame_name = 'xhr-post-frame';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function(sw) {
         return new Promise(function(resolve) {
            var frame = document.createElement('iframe');
            frame.name = frame_name;
            document.body.appendChild(frame);
            var form = document.createElement('form');
            form.target = frame_name;
            form.action = scope;
            form.method = 'post';
            var input1 = document.createElement('input');
            input1.type = 'text';
            input1.value = 'testValue1';
            input1.name = 'testName1'
            form.appendChild(input1);
            var input2 = document.createElement('input');
            input2.type = 'text';
            input2.value = 'testValue2';
            input2.name = 'testName2'
            form.appendChild(input2);
            document.body.appendChild(form);
            frame.onload = function() {
              document.body.removeChild(form);
              resolve(frame);
            };
            form.submit();
          });
        })
      .then(function(frame) {
          assert_equals(frame.contentDocument.body.textContent,
                        'POST:application/x-www-form-urlencoded:' +
                        'testName1=testValue1&testName2=testValue2');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with POST form');

async_test(function(t) {
    var scope = 'resources/simple.html?multiple-respond-with';
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(
            frame.contentDocument.body.textContent,
            '(0)(1)[InvalidStateError](2)[InvalidStateError]',
            'Multiple calls of respondWith must throw InvalidStateErrors.');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Multiple calls of respondWith must throw InvalidStateErrors');

async_test(function(t) {
    var scope = 'resources/simple.html?used-check';
    var first_frame;
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(frame) {
          assert_equals(frame.contentDocument.body.textContent,
                        'Here\'s an other html file.\n',
                        'Response should come from fetched other file');
          first_frame = frame;
          return with_iframe(scope);
        })
      .then(function(frame) {
          // When we access to the scope in the second time, the content of the
          // response is generated inside the ServiceWorker. The body contains
          // the value of bodyUsed of the first response which is already
          // consumed by FetchEvent.respondWith method.
          assert_equals(
            frame.contentDocument.body.textContent,
            'bodyUsed: true',
            'event.respondWith must set the used flag.');
          first_frame.remove();
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker event.respondWith must set the used flag');

async_test(function(t) {
    var scope = 'resources/simple.html?fragment-check';
    var fragment = '#/some/fragment';
    var first_frame;
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope + fragment); })
      .then(function(frame) {
          assert_equals(
            frame.contentDocument.body.textContent,
            'Fragment Not Found',
            'Service worker should not expose URL fragments.');
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker must not expose FetchEvent URL fragments.');

async_test(function(t) {
    var scope = 'resources/simple.html?cache';
    var frame;
    var cacheTypes = [
      undefined, 'default', 'no-store', 'reload', 'no-cache', 'force-cache'
    ];
    service_worker_unregister_and_register(t, worker, scope)
      .then(function(reg) {
          return wait_for_state(t, reg.installing, 'activated');
        })
      .then(function() { return with_iframe(scope); })
      .then(function(f) {
          frame = f;
          var tests = cacheTypes.map(function(type) {
            return new Promise(function(resolve) {
                return frame.contentWindow.fetch(scope + '=' + type,
                                                 {cache: type})
                  .then(function(response) { return response.text(); })
                  .then(function(response_text) {
                      var expected = (type === undefined) ? 'default' : type;
                      assert_equals(response_text, expected,
                                    'Service Worker should respond to fetch with the correct type');
                    })
                  .then(resolve);
              });
          });
          return Promise.all(tests);
        })
      .then(function() {
          frame.remove();
          return service_worker_unregister_and_done(t, scope);
        })
      .catch(unreached_rejection(t));
  }, 'Service Worker responds to fetch event with the correct cache types');

</script>
</body>