OLD | NEW |
1 // Adapter for testharness.js-style tests with Service Workers | 1 // Adapter for testharness.js-style tests with Service Workers |
2 | 2 |
3 function service_worker_unregister_and_register(test, url, scope) { | 3 function service_worker_unregister_and_register(test, url, scope) { |
4 if (!scope || scope.length == 0) | 4 if (!scope || scope.length == 0) |
5 return Promise.reject(new Error('tests must define a scope')); | 5 return Promise.reject(new Error('tests must define a scope')); |
6 | 6 |
7 var options = { scope: scope }; | 7 var options = { scope: scope }; |
8 return service_worker_unregister(test, scope) | 8 return service_worker_unregister(test, scope) |
9 .then(function() { | 9 .then(function() { |
10 return navigator.serviceWorker.register(url, options); | 10 return navigator.serviceWorker.register(url, options); |
11 }) | 11 }) |
12 .catch(unreached_rejection(test, | 12 .catch(unreached_rejection(test, |
13 'unregister and register should not fail')); | 13 'unregister and register should not fail')); |
14 } | 14 } |
15 | 15 |
16 function service_worker_unregister(test, documentUrl) { | 16 function service_worker_unregister(test, documentUrl) { |
17 return navigator.serviceWorker.getRegistration(documentUrl) | 17 return navigator.serviceWorker.getRegistration(documentUrl) |
18 .then(function(registration) { | 18 .then(function(registration) { |
19 if (registration) | 19 if (registration) |
20 return registration.unregister(); | 20 return registration.unregister(); |
21 }) | 21 }) |
22 .catch(unreached_rejection(test, 'unregister should not fail')); | 22 .catch(unreached_rejection(test, 'unregister should not fail')); |
23 } | 23 } |
24 | 24 |
25 function service_worker_unregister_and_done(test, scope) { | 25 function service_worker_unregister_and_done(test, scope) { |
26 return service_worker_unregister(test, scope) | 26 return service_worker_unregister(test, scope) |
27 .then(test.done.bind(test)); | 27 .then(test.done.bind(test)); |
28 } | 28 } |
29 | 29 |
30 // Rejection-specific helper that provides more details | 30 // Rejection-specific helper that provides more details |
31 function unreached_rejection(test, prefix) { | 31 function unreached_rejection(test, prefix) { |
32 return test.step_func(function(error) { | 32 return test.step_func(function(error) { |
33 var reason = error.message || error.name || error; | 33 var reason = error.message || error.name || error; |
34 var error_prefix = prefix || 'unexpected rejection'; | 34 var error_prefix = prefix || 'unexpected rejection'; |
35 assert_unreached(error_prefix + ': ' + reason); | 35 assert_unreached(error_prefix + ': ' + reason); |
36 }); | 36 }); |
37 } | 37 } |
38 | 38 |
39 // FIXME: Clean up the iframe when the test completes. | 39 // FIXME: Clean up the iframe when the test completes. |
40 function with_iframe(url, f) { | 40 function with_iframe(url, f) { |
41 return new Promise(function(resolve, reject) { | 41 return new Promise(function(resolve, reject) { |
42 var frame = document.createElement('iframe'); | 42 var frame = document.createElement('iframe'); |
43 frame.src = url; | 43 frame.src = url; |
44 frame.onload = function() { | 44 frame.onload = function() { |
45 if (f) { | 45 if (f) { |
46 f(frame); | 46 f(frame); |
47 } | 47 } |
48 resolve(frame); | 48 resolve(frame); |
49 }; | 49 }; |
50 document.body.appendChild(frame); | 50 document.body.appendChild(frame); |
51 }); | 51 }); |
52 } | 52 } |
53 | 53 |
54 function unload_iframe(iframe) { | 54 function unload_iframe(iframe) { |
55 var saw_unload = new Promise(function(resolve) { | 55 var saw_unload = new Promise(function(resolve) { |
56 iframe.contentWindow.addEventListener('unload', function() { | 56 iframe.contentWindow.addEventListener('unload', function() { |
57 resolve(); | 57 resolve(); |
58 }); | 58 }); |
59 }); | 59 }); |
60 iframe.src = ''; | 60 iframe.src = ''; |
61 iframe.remove(); | 61 iframe.remove(); |
62 return saw_unload; | 62 return saw_unload; |
63 } | 63 } |
64 | 64 |
65 function normalizeURL(url) { | 65 function normalizeURL(url) { |
66 return new URL(url, document.location).toString().replace(/#.*$/, ''); | 66 return new URL(url, document.location).toString().replace(/#.*$/, ''); |
67 } | 67 } |
68 | 68 |
69 function get_newest_worker(registration) { | 69 function get_newest_worker(registration) { |
70 if (!registration) { | 70 if (!registration) { |
71 return Promise.reject(new Error( | 71 return Promise.reject(new Error( |
72 'get_newest_worker must be passed a ServiceWorkerRegistration')); | 72 'get_newest_worker must be passed a ServiceWorkerRegistration')); |
73 } | 73 } |
74 if (registration.installing) | 74 if (registration.installing) |
75 return Promise.resolve(registration.installing); | 75 return Promise.resolve(registration.installing); |
76 if (registration.waiting) | 76 if (registration.waiting) |
77 return Promise.resolve(registration.waiting); | 77 return Promise.resolve(registration.waiting); |
78 if (registration.active) | 78 if (registration.active) |
79 return Promise.resolve(registration.active); | 79 return Promise.resolve(registration.active); |
80 return Promise.reject(new Error( | 80 return Promise.reject(new Error( |
81 'registration must have at least one version')); | 81 'registration must have at least one version')); |
82 } | 82 } |
83 | 83 |
84 function wait_for_update(test, registration) { | 84 function wait_for_update(test, registration) { |
85 if (!registration || registration.unregister == undefined) { | 85 if (!registration || registration.unregister == undefined) { |
86 return Promise.reject(new Error( | 86 return Promise.reject(new Error( |
87 'wait_for_update must be passed a ServiceWorkerRegistration')); | 87 'wait_for_update must be passed a ServiceWorkerRegistration')); |
88 } | 88 } |
89 | 89 |
90 return new Promise(test.step_func(function(resolve) { | 90 return new Promise(test.step_func(function(resolve) { |
91 registration.addEventListener('updatefound', test.step_func(function() { | 91 registration.addEventListener('updatefound', test.step_func(function() { |
92 resolve(registration.installing); | 92 resolve(registration.installing); |
93 })); | 93 })); |
94 })); | 94 })); |
95 } | 95 } |
96 | 96 |
97 function wait_for_state(test, worker, state) { | 97 function wait_for_state(test, worker, state) { |
98 if (!worker || worker.state == undefined) { | 98 if (!worker || worker.state == undefined) { |
99 return Promise.reject(new Error( | 99 return Promise.reject(new Error( |
100 'wait_for_state must be passed a ServiceWorker')); | 100 'wait_for_state must be passed a ServiceWorker')); |
101 } | 101 } |
102 if (worker.state === state) | 102 if (worker.state === state) |
103 return Promise.resolve(state); | 103 return Promise.resolve(state); |
104 | 104 |
105 if (state === 'installing') { | 105 if (state === 'installing') { |
106 switch (worker.state) { | 106 switch (worker.state) { |
107 case 'installed': | 107 case 'installed': |
108 case 'activating': | 108 case 'activating': |
109 case 'activated': | 109 case 'activated': |
110 case 'redundant': | 110 case 'redundant': |
111 return Promise.reject(new Error( | 111 return Promise.reject(new Error( |
112 'worker is ' + worker.state + ' but waiting for ' + state)); | 112 'worker is ' + worker.state + ' but waiting for ' + state)); |
113 } | 113 } |
114 } | 114 } |
115 | 115 |
116 if (state === 'installed') { | 116 if (state === 'installed') { |
117 switch (worker.state) { | 117 switch (worker.state) { |
118 case 'activating': | 118 case 'activating': |
119 case 'activated': | 119 case 'activated': |
120 case 'redundant': | 120 case 'redundant': |
121 return Promise.reject(new Error( | 121 return Promise.reject(new Error( |
122 'worker is ' + worker.state + ' but waiting for ' + state)); | 122 'worker is ' + worker.state + ' but waiting for ' + state)); |
123 } | 123 } |
124 } | 124 } |
125 | 125 |
126 if (state === 'activating') { | 126 if (state === 'activating') { |
127 switch (worker.state) { | 127 switch (worker.state) { |
128 case 'activated': | 128 case 'activated': |
129 case 'redundant': | 129 case 'redundant': |
130 return Promise.reject(new Error( | 130 return Promise.reject(new Error( |
131 'worker is ' + worker.state + ' but waiting for ' + state)); | 131 'worker is ' + worker.state + ' but waiting for ' + state)); |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 if (state === 'activated') { | 135 if (state === 'activated') { |
136 switch (worker.state) { | 136 switch (worker.state) { |
137 case 'redundant': | 137 case 'redundant': |
138 return Promise.reject(new Error( | 138 return Promise.reject(new Error( |
139 'worker is ' + worker.state + ' but waiting for ' + state)); | 139 'worker is ' + worker.state + ' but waiting for ' + state)); |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 return new Promise(test.step_func(function(resolve) { | 143 return new Promise(test.step_func(function(resolve) { |
144 worker.addEventListener('statechange', test.step_func(function() { | 144 worker.addEventListener('statechange', test.step_func(function() { |
145 if (worker.state === state) | 145 if (worker.state === state) |
146 resolve(state); | 146 resolve(state); |
147 })); | 147 })); |
148 })); | 148 })); |
149 } | 149 } |
150 | 150 |
151 function wait_for_activated(test, registration) { | 151 function wait_for_activated(test, registration) { |
152 var expected_state = 'activated'; | 152 var expected_state = 'activated'; |
153 if (registration.active) | 153 if (registration.active) |
154 return wait_for_state(test, registration.active, expected_state); | 154 return wait_for_state(test, registration.active, expected_state); |
155 if (registration.waiting) | 155 if (registration.waiting) |
156 return wait_for_state(test, registration.waiting, expected_state); | 156 return wait_for_state(test, registration.waiting, expected_state); |
157 if (registration.installing) | 157 if (registration.installing) |
158 return wait_for_state(test, registration.installing, expected_state); | 158 return wait_for_state(test, registration.installing, expected_state); |
159 return Promise.reject( | 159 return Promise.reject( |
160 new Error('registration must have at least one version')); | 160 new Error('registration must have at least one version')); |
161 } | 161 } |
162 | 162 |
163 (function() { | 163 (function() { |
164 function fetch_tests_from_worker(worker) { | 164 function fetch_tests_from_worker(worker) { |
165 return new Promise(function(resolve, reject) { | 165 return new Promise(function(resolve, reject) { |
166 var messageChannel = new MessageChannel(); | 166 var messageChannel = new MessageChannel(); |
167 messageChannel.port1.addEventListener('message', function(message) { | 167 messageChannel.port1.addEventListener('message', function(message) { |
168 if (message.data.type == 'complete') { | 168 if (message.data.type == 'complete') { |
169 synthesize_tests(message.data.tests, message.data.status); | 169 synthesize_tests(message.data.tests, message.data.status); |
170 resolve(); | 170 resolve(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 .then(function(worker) { return fetch_tests_from_worker(worker); }) | 212 .then(function(worker) { return fetch_tests_from_worker(worker); }) |
213 .then(function() { return registration.unregister(); }) | 213 .then(function() { return registration.unregister(); }) |
214 .then(function() { test.done(); }) | 214 .then(function() { test.done(); }) |
215 .catch(test.step_func(function(e) { throw e; })); | 215 .catch(test.step_func(function(e) { throw e; })); |
216 }; | 216 }; |
217 | 217 |
218 self.service_worker_test = service_worker_test; | 218 self.service_worker_test = service_worker_test; |
219 })(); | 219 })(); |
220 | 220 |
221 function get_host_info() { | 221 function get_host_info() { |
222 var ORIGINAL_HOST = '127.0.0.1'; | 222 var ORIGINAL_HOST = '127.0.0.1'; |
223 var REMOTE_HOST = 'localhost'; | 223 var REMOTE_HOST = 'localhost'; |
224 var UNAUTHENTICATED_HOST = 'example.test'; | 224 var UNAUTHENTICATED_HOST = 'example.test'; |
225 var HTTP_PORT = 8000; | 225 var HTTP_PORT = 8000; |
226 var HTTPS_PORT = 8443; | 226 var HTTPS_PORT = 8443; |
227 try { | 227 try { |
228 // In W3C test, we can get the hostname and port number in config.json | 228 // In W3C test, we can get the hostname and port number in config.json |
229 // using wptserve's built-in pipe. | 229 // using wptserve's built-in pipe. |
230 // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes | 230 // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes |
231 HTTP_PORT = eval('{{ports[http][0]}}'); | 231 HTTP_PORT = eval('{{ports[http][0]}}'); |
232 HTTPS_PORT = eval('{{ports[https][0]}}'); | 232 HTTPS_PORT = eval('{{ports[https][0]}}'); |
233 ORIGINAL_HOST = eval('\'{{host}}\''); | 233 ORIGINAL_HOST = eval('\'{{host}}\''); |
234 REMOTE_HOST = 'www1.' + ORIGINAL_HOST; | 234 REMOTE_HOST = 'www1.' + ORIGINAL_HOST; |
235 } catch(e) { | 235 } catch (e) { |
236 } | 236 } |
237 return { | 237 return { |
238 HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, | 238 HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, |
239 HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, | 239 HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, |
240 HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, | 240 HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, |
241 HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, | 241 HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, |
242 UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PO
RT | 242 UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT |
243 }; | 243 }; |
244 } | 244 } |
245 | 245 |
246 function base_path() { | 246 function base_path() { |
247 return location.pathname.replace(/\/[^\/]*$/, '/'); | 247 return location.pathname.replace(/\/[^\/]*$/, '/'); |
248 } | 248 } |
249 | 249 |
250 function test_login(test, origin, username, password) { | 250 function test_login(test, origin, username, password) { |
251 return new Promise(function(resolve, reject) { | 251 return new Promise(function(resolve, reject) { |
252 with_iframe( | 252 with_iframe( |
253 origin + base_path() + | 253 origin + base_path() + |
254 'resources/fetch-access-control-login.html') | 254 'resources/fetch-access-control-login.html') |
255 .then(test.step_func(function(frame) { | 255 .then(test.step_func(function(frame) { |
256 var channel = new MessageChannel(); | 256 var channel = new MessageChannel(); |
257 channel.port1.onmessage = test.step_func(function() { | 257 channel.port1.onmessage = test.step_func(function() { |
258 unload_iframe(frame).catch(function() {}); | 258 unload_iframe(frame).catch(function() {}); |
259 resolve(); | 259 resolve(); |
260 }); | 260 }); |
261 frame.contentWindow.postMessage( | 261 frame.contentWindow.postMessage( |
262 {username: username, password: password}, | 262 {username: username, password: password}, |
263 [channel.port2], origin); | 263 [channel.port2], origin); |
264 })); | 264 })); |
265 }); | 265 }); |
266 } | 266 } |
OLD | NEW |