Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / http / tests / serviceworker / resources / test-helpers.js
index 5a98fcb..caa6ea7 100644 (file)
 // Adapter for testharness.js-style tests with Service Workers
 
-function service_worker_test(url, description) {
-    var t = async_test(description);
-    t.step(function() {
-
-        navigator.serviceWorker.register(url, {scope:'nonexistent'}).then(
-            t.step_func(function(worker) {
-                var messageChannel = new MessageChannel();
-                messageChannel.port1.onmessage = t.step_func(onMessage);
-                worker.postMessage({port:messageChannel.port2}, [messageChannel.port2]);
-            }),
-            unreached_rejection(t, 'Registration should succeed, but failed')
-        );
-
-        function onMessage(e) {
-            assert_equals(e.data, 'pass');
-            t.done();
-        }
-    });
+function service_worker_unregister_and_register(test, url, scope) {
+  if (!scope || scope.length == 0)
+    return Promise.reject(new Error('tests must define a scope'));
+
+  var options = { scope: scope };
+  return service_worker_unregister(test, scope)
+      .then(function() {
+          return navigator.serviceWorker.register(url, options);
+        })
+      .catch(unreached_rejection(test,
+                                 'unregister and register should not fail'));
 }
 
-// FIXME: Replace this with test.unreached_func(desc) once testharness.js is updated
-// Use with unexpected event handlers or Promise rejection.
-// E.g.:
-//    onbadevent = fail(t, 'Should only see good events');
-//    Promise.then(...).catch(fail(t, 'Rejection is never fun'));
-function unreached_func(test, desc) {
-    return test.step_func(function() {
-        assert_unreached(desc);
-    });
+function service_worker_unregister(test, documentUrl) {
+  return navigator.serviceWorker.getRegistration(documentUrl)
+      .then(function(registration) {
+          if (registration)
+            return registration.unregister();
+        })
+      .catch(unreached_rejection(test, 'unregister should not fail'));
+}
+
+function service_worker_unregister_and_done(test, scope) {
+  return service_worker_unregister(test, scope)
+      .then(test.done.bind(test));
 }
 
 // Rejection-specific helper that provides more details
 function unreached_rejection(test, prefix) {
-    return test.step_func(function(reason) {
-        assert_unreached(prefix + ': ' + reason.name);
+    return test.step_func(function(error) {
+        var reason = error.message || error.name || error;
+        var error_prefix = prefix || 'unexpected rejection';
+        assert_unreached(error_prefix + ': ' + reason);
     });
 }
 
 // FIXME: Clean up the iframe when the test completes.
 function with_iframe(url, f) {
-  var frame = document.createElement('iframe');
-  frame.src = url;
-  frame.onload = function() {
-      f(frame);
+    return new Promise(function(resolve, reject) {
+        var frame = document.createElement('iframe');
+        frame.src = url;
+        frame.onload = function() {
+            if (f) {
+              f(frame);
+            }
+            resolve(frame);
+        };
+        document.body.appendChild(frame);
+    });
+}
+
+function unload_iframe(iframe) {
+  var saw_unload = new Promise(function(resolve) {
+      iframe.contentWindow.addEventListener('unload', function() {
+          resolve();
+        });
+    });
+  iframe.src = '';
+  iframe.remove();
+  return saw_unload;
+}
+
+function normalizeURL(url) {
+  return new URL(url, document.location).toString().replace(/#.*$/, '');
+}
+
+function get_newest_worker(registration) {
+  if (!registration) {
+    return Promise.reject(new Error(
+        'get_newest_worker must be passed a ServiceWorkerRegistration'));
+  }
+  if (registration.installing)
+    return Promise.resolve(registration.installing);
+  if (registration.waiting)
+    return Promise.resolve(registration.waiting);
+  if (registration.active)
+    return Promise.resolve(registration.active);
+  return Promise.reject(new Error(
+      'registration must have at least one version'));
+}
+
+function wait_for_update(test, registration) {
+  if (!registration || registration.unregister == undefined) {
+    return Promise.reject(new Error(
+        'wait_for_update must be passed a ServiceWorkerRegistration'));
+  }
+
+  return new Promise(test.step_func(function(resolve) {
+      registration.addEventListener('updatefound', test.step_func(function() {
+          resolve(registration.installing);
+      }));
+    }));
+}
+
+function wait_for_state(test, worker, state) {
+  if (!worker || worker.state == undefined) {
+    return Promise.reject(new Error(
+        'wait_for_state must be passed a ServiceWorker'));
+  }
+  if (worker.state === state)
+    return Promise.resolve(state);
+
+  if (state === 'installing') {
+    switch (worker.state) {
+    case 'installed':
+    case 'activating':
+    case 'activated':
+    case 'redundant':
+      return Promise.reject(new Error(
+          'worker is ' + worker.state + ' but waiting for ' + state));
+    }
+  }
+
+  if (state === 'installed') {
+    switch (worker.state) {
+    case 'activating':
+    case 'activated':
+    case 'redundant':
+      return Promise.reject(new Error(
+          'worker is ' + worker.state + ' but waiting for ' + state));
+    }
+  }
+
+  if (state === 'activating') {
+    switch (worker.state) {
+    case 'activated':
+    case 'redundant':
+      return Promise.reject(new Error(
+          'worker is ' + worker.state + ' but waiting for ' + state));
+    }
+  }
+
+  if (state === 'activated') {
+    switch (worker.state) {
+    case 'redundant':
+      return Promise.reject(new Error(
+          'worker is ' + worker.state + ' but waiting for ' + state));
+    }
+  }
+
+  return new Promise(test.step_func(function(resolve) {
+      worker.addEventListener('statechange', test.step_func(function() {
+          if (worker.state === state)
+            resolve(state);
+        }));
+    }));
+}
+
+function wait_for_activated(test, registration) {
+  var expected_state = 'activated';
+  if (registration.active)
+    return wait_for_state(test, registration.active, expected_state);
+  if (registration.waiting)
+    return wait_for_state(test, registration.waiting, expected_state);
+  if (registration.installing)
+    return wait_for_state(test, registration.installing, expected_state);
+  return Promise.reject(
+      new Error('registration must have at least one version'));
+}
+
+(function() {
+  function fetch_tests_from_worker(worker) {
+    return new Promise(function(resolve, reject) {
+        var messageChannel = new MessageChannel();
+        messageChannel.port1.addEventListener('message', function(message) {
+            if (message.data.type == 'complete') {
+              synthesize_tests(message.data.tests, message.data.status);
+              resolve();
+            }
+          });
+        worker.postMessage({type: 'fetch_results', port: messageChannel.port2},
+                           [messageChannel.port2]);
+        messageChannel.port1.start();
+      });
   };
-  document.body.appendChild(frame);
+
+  function synthesize_tests(tests, status) {
+    for (var i = 0; i < tests.length; ++i) {
+      var t = async_test(tests[i].name);
+      switch (tests[i].status) {
+        case tests[i].PASS:
+          t.step(function() { assert_true(true); });
+          t.done();
+          break;
+        case tests[i].TIMEOUT:
+          t.force_timeout();
+          break;
+        case tests[i].FAIL:
+          t.step(function() { throw {message: tests[i].message}; });
+          break;
+        case tests[i].NOTRUN:
+          // Leave NOTRUN alone. It'll get marked as a NOTRUN when the test
+          // terminates.
+          break;
+      }
+    }
+  };
+
+  function service_worker_test(url, description) {
+    var scope = window.location.origin + '/service-worker-scope' +
+      window.location.pathname;
+
+    var test = async_test(description);
+    var registration;
+    service_worker_unregister_and_register(test, url, scope)
+      .then(function(r) {
+          registration = r;
+          return wait_for_update(test, registration);
+        })
+      .then(function(worker) { return fetch_tests_from_worker(worker); })
+      .then(function() { return registration.unregister(); })
+      .then(function() { test.done(); })
+      .catch(test.step_func(function(e) { throw e; }));
+  };
+
+  self.service_worker_test = service_worker_test;
+})();
+
+function get_host_info() {
+    var ORIGINAL_HOST = '127.0.0.1';
+    var REMOTE_HOST = 'localhost';
+    var UNAUTHENTICATED_HOST = 'example.test';
+    var HTTP_PORT = 8000;
+    var HTTPS_PORT = 8443;
+    try {
+        // In W3C test, we can get the hostname and port number in config.json
+        // using wptserve's built-in pipe.
+        // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
+        HTTP_PORT = eval('{{ports[http][0]}}');
+        HTTPS_PORT = eval('{{ports[https][0]}}');
+        ORIGINAL_HOST = eval('\'{{host}}\'');
+        REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
+    } catch(e) {
+    }
+    return {
+        HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT,
+        HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
+        HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
+        HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
+        UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
+    };
+}
+
+function base_path() {
+    return location.pathname.replace(/\/[^\/]*$/, '/');
 }