Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / http / tests / serviceworker / resources / test-helpers.js
blob02be72e83af17fa002c4a697871f289fda25998d
1 // Adapter for testharness.js-style tests with Service Workers
3 function service_worker_unregister_and_register(test, url, scope) {
4   if (!scope || scope.length == 0)
5     return Promise.reject(new Error('tests must define a scope'));
7   var options = { scope: scope };
8   return service_worker_unregister(test, scope)
9     .then(function() {
10         return navigator.serviceWorker.register(url, options);
11       })
12     .catch(unreached_rejection(test,
13                                'unregister and register should not fail'));
16 function service_worker_unregister(test, documentUrl) {
17   return navigator.serviceWorker.getRegistration(documentUrl)
18     .then(function(registration) {
19         if (registration)
20           return registration.unregister();
21       })
22     .catch(unreached_rejection(test, 'unregister should not fail'));
25 function service_worker_unregister_and_done(test, scope) {
26   return service_worker_unregister(test, scope)
27     .then(test.done.bind(test));
30 function unreached_fulfillment(test, prefix) {
31   return test.step_func(function(result) {
32       var error_prefix = prefix || 'unexpected fulfillment';
33       assert_unreached(error_prefix + ': ' + result);
34     });
37 // Rejection-specific helper that provides more details
38 function unreached_rejection(test, prefix) {
39   return test.step_func(function(error) {
40       var reason = error.message || error.name || error;
41       var error_prefix = prefix || 'unexpected rejection';
42       assert_unreached(error_prefix + ': ' + reason);
43     });
46 // Adds an iframe to the document and returns a promise that resolves to the
47 // iframe when it finishes loading. The caller is responsible for removing the
48 // iframe later if needed.
49 function with_iframe(url) {
50   return new Promise(function(resolve) {
51       var frame = document.createElement('iframe');
52       frame.src = url;
53       frame.onload = function() { resolve(frame); };
54       document.body.appendChild(frame);
55     });
58 function with_sandboxed_iframe(url, sandbox) {
59   return new Promise(function(resolve) {
60       var frame = document.createElement('iframe');
61       frame.sandbox = sandbox;
62       frame.src = url;
63       frame.onload = function() { resolve(frame); };
64       document.body.appendChild(frame);
65     });
68 function normalizeURL(url) {
69   return new URL(url, self.location).toString().replace(/#.*$/, '');
72 function wait_for_update(test, registration) {
73   if (!registration || registration.unregister == undefined) {
74     return Promise.reject(new Error(
75       'wait_for_update must be passed a ServiceWorkerRegistration'));
76   }
78   return new Promise(test.step_func(function(resolve) {
79       registration.addEventListener('updatefound', test.step_func(function() {
80           resolve(registration.installing);
81         }));
82     }));
85 function wait_for_state(test, worker, state) {
86   if (!worker || worker.state == undefined) {
87     return Promise.reject(new Error(
88       'wait_for_state must be passed a ServiceWorker'));
89   }
90   if (worker.state === state)
91     return Promise.resolve(state);
93   if (state === 'installing') {
94     switch (worker.state) {
95       case 'installed':
96       case 'activating':
97       case 'activated':
98       case 'redundant':
99         return Promise.reject(new Error(
100           'worker is ' + worker.state + ' but waiting for ' + state));
101     }
102   }
104   if (state === 'installed') {
105     switch (worker.state) {
106       case 'activating':
107       case 'activated':
108       case 'redundant':
109         return Promise.reject(new Error(
110           'worker is ' + worker.state + ' but waiting for ' + state));
111     }
112   }
114   if (state === 'activating') {
115     switch (worker.state) {
116       case 'activated':
117       case 'redundant':
118         return Promise.reject(new Error(
119           'worker is ' + worker.state + ' but waiting for ' + state));
120     }
121   }
123   if (state === 'activated') {
124     switch (worker.state) {
125       case 'redundant':
126         return Promise.reject(new Error(
127           'worker is ' + worker.state + ' but waiting for ' + state));
128     }
129   }
131   return new Promise(test.step_func(function(resolve) {
132       worker.addEventListener('statechange', test.step_func(function() {
133           if (worker.state === state)
134             resolve(state);
135         }));
136     }));
139 // Declare a test that runs entirely in the ServiceWorkerGlobalScope. The |url|
140 // is the service worker script URL. This function:
141 // - Instantiates a new test with the description specified in |description|.
142 //   The test will succeed if the specified service worker can be successfully
143 //   registered and installed.
144 // - Creates a new ServiceWorker registration with a scope unique to the current
145 //   document URL. Note that this doesn't allow more than one
146 //   service_worker_test() to be run from the same document.
147 // - Waits for the new worker to begin installing.
148 // - Imports tests results from tests running inside the ServiceWorker.
149 function service_worker_test(url, description) {
150   // If the document URL is https://example.com/document and the script URL is
151   // https://example.com/script/worker.js, then the scope would be
152   // https://example.com/script/scope/document.
153   var scope = new URL('scope' + window.location.pathname,
154                       new URL(url, window.location)).toString();
155   promise_test(function(test) {
156       return service_worker_unregister_and_register(test, url, scope)
157         .then(function(registration) {
158             add_completion_callback(function() {
159                 registration.unregister();
160               });
161             return wait_for_update(test, registration)
162               .then(function(worker) {
163                   return fetch_tests_from_worker(worker);
164                 });
165           });
166     }, description);
169 function base_path() {
170   return location.pathname.replace(/\/[^\/]*$/, '/');
173 function test_login(test, origin, username, password, cookie) {
174   return new Promise(function(resolve, reject) {
175       with_iframe(
176         origin +
177         '/serviceworker/resources/fetch-access-control-login.html')
178         .then(test.step_func(function(frame) {
179             var channel = new MessageChannel();
180             channel.port1.onmessage = test.step_func(function() {
181                 frame.remove();
182                 resolve();
183               });
184             frame.contentWindow.postMessage(
185               {username: username, password: password, cookie: cookie},
186               origin, [channel.port2]);
187           }));
188     });
191 function login(test, local, remote) {
192   var suffix = (local.indexOf("https") != -1) ? "s": "";
193   return test_login(test, local, 'username1' + suffix, 'password1' + suffix,
194                     'cookie1')
195     .then(function() {
196         return test_login(test, remote, 'username2' + suffix,
197                           'password2' + suffix, 'cookie2');
198       });
201 // Helper for testing with ServiceWorkerRegistration objects. Compares simple
202 // attributes defined on the interfaces.
203 function assert_registration_equals(actual, expected, description) {
204   assert_class_string(actual, 'ServiceWorkerRegistration', description);
205   ['scope', 'installing', 'waiting', 'active'].forEach(function(attribute) {
206       assert_equals(actual[attribute], expected[attribute],
207                     description + ' Attributes differ: ' + attribute + '.');
208     });
211 // Asserts that two arrays |actual| and |expected| contain the same set of
212 // ServiceWorkerRegistration as determined by assert_registration_equals(). The
213 // corresponding elements must occupy corresponding indices in their respective
214 // arrays.
215 function assert_registration_array_equals(actual, expected, description) {
216   assert_true(Array.isArray(actual), description);
217   assert_equals(actual.length, expected.length, description);
218   actual.forEach(function(value, index) {
219       assert_registration_equals(value, expected[index],
220                                  description + ' :  object[' + index + ']');
221     });