| <!DOCTYPE html> |
| <!-- |
| Copyright 2022 The Cobalt Authors. All Rights Reserved. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <!-- |
| Note: This is a very basic test of the existing minimal Service Worker |
| functionality. This can be expanded as more functionality is implemented. |
| --> |
| |
| <html> |
| |
| <head> |
| <title>Cobalt Service Worker Test</title> |
| <script src='black_box_js_test_utils.js'></script> |
| </head> |
| |
| <body> |
| <script> |
| var expected_event_count = 0; |
| |
| function count_event(expected_value) { |
| expected_event_count += 1; |
| console.log('Expected events counted:', expected_event_count) |
| if (expected_value) { |
| assertEqual(expected_value, expected_event_count) |
| } |
| } |
| |
| function test_claimable_worker() { |
| console.log('Adding ready promise.'); |
| navigator.serviceWorker.ready.then(function ( |
| registration) { |
| assertNotEqual(null, registration); |
| console.log('(Expected) Registration ready promise', |
| registration, ' with active worker ', |
| registration.active); |
| assertNotEqual(null, registration.active); |
| registration.active.postMessage( |
| 'Registration ready received for claimable worker.'); |
| count_event(); |
| registration.unregister() |
| .then(function (success) { |
| // Even a claimed registration will successfully |
| // unregister because unregistration takes effect after |
| // the page is unloaded, so it's not blocked by being |
| // the active service worker. |
| console.log('(Expected) unregister success :', |
| success); |
| count_event(41); |
| }, function (error) { |
| console.log('(Unexpected) unregister ' + |
| `${error}`, error); |
| assertIncludes('SecurityError: ', `${error}`); |
| notReached(); |
| }); |
| console.log('unregister started.'); |
| |
| }); |
| |
| navigator.serviceWorker.register('service_worker_test_claimable.js', { |
| scope: './', |
| }).then(function (registration) { |
| worker = registration.installing; |
| if (worker) { |
| console.log('claimable worker registered (installing).'); |
| worker.postMessage( |
| 'Registration successful, current worker state is ' + |
| 'installing.'); |
| } |
| worker = registration.waiting; |
| if (worker) { |
| console.log('claimable worker registered (waiting).'); |
| worker.postMessage( |
| 'Registration successful, current worker state is ' + |
| 'waiting.'); |
| } |
| worker = registration.active; |
| if (worker) { |
| console.log('claimable worker registered (active).'); |
| worker.postMessage( |
| 'Registration successful, current worker state is ' + |
| 'active.'); |
| } |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| } |
| |
| console.log('Starting tests'); |
| if ('serviceWorker' in navigator) { |
| navigator.serviceWorker.ready.then(function (registration) { |
| assertNotEqual(null, registration); |
| console.log('(Expected) Registration ready promise', |
| registration, 'with active worker ', registration.active); |
| assertNotEqual(null, registration.active); |
| count_event(); |
| }); |
| |
| navigator.serviceWorker.oncontrollerchange = function (event) { |
| console.log('Got oncontrollerchange event', event.target); |
| count_event(40); |
| } |
| |
| navigator.serviceWorker.onmessage = function (event) { |
| console.log('Got onmessage event', event.target, event.data); |
| } |
| |
| navigator.serviceWorker.register('http://..:..') |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test invalid script URL:', error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(1); |
| }); |
| navigator.serviceWorker.register('arg:service_worker_test.js') |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test script URL that is not http ' + |
| 'or https:', error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(2); |
| }); |
| navigator.serviceWorker.register('http:%2fservice_worker_test.js') |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test script URL with escaped slash:', |
| error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(3); |
| }); |
| navigator.serviceWorker.register('service_worker_test.js', { |
| scope: 'http://..:..', |
| }) |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test invalid scope URL:', error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(4); |
| }); |
| navigator.serviceWorker.register('service_worker_test.js', { |
| scope: 'arg:/', |
| }) |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test scope URL that is not http ' + |
| 'or https:', error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(5); |
| }); |
| navigator.serviceWorker.register('service_worker_test.js', { |
| scope: '/%5c', |
| }) |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test scope URL with escaped slash:', |
| error); |
| assertIncludes('TypeError', `${error}`); |
| count_event(6); |
| }); |
| // Repeat a few times to test the 'equivalent job' and finish job |
| // logic. |
| for (let repeated = 0; repeated < 15; repeated++) { |
| navigator.serviceWorker.register('http://www.example.com/', { |
| scope: '/', |
| }) |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test Script URL is not ' + |
| `trusted: ${error}`, error); |
| assertIncludes('SecurityError: ', `${error}`); |
| count_event(); |
| }); |
| } |
| navigator.serviceWorker.register('http://127.0.0.100:2345/') |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test script URL with different ' + |
| `origin: ${error}`, error); |
| assertIncludes('SecurityError: ', `${error}`); |
| count_event(); |
| }); |
| |
| navigator.serviceWorker.register('service_worker_test.js', { |
| scope: 'http://127.0.0.100:2345/', |
| }) |
| .then(function (registration) { |
| console.log('(Unexpected) :', registration); |
| notReached(); |
| }, function (error) { |
| console.log('(Expected) Test scope URL with different ' + |
| `origin: ${error}`, error); |
| assertIncludes('SecurityError: ', `${error}`); |
| count_event(); |
| }); |
| |
| // Finally, test a succeeding registration. |
| navigator.serviceWorker.register('service_worker_test.js', { |
| scope: 'registration/scope', |
| }) |
| .then(function (registration) { |
| console.log('(Expected) Registration Succeeded:', |
| registration); |
| assertNotEqual(null, registration); |
| // The default value for RegistrationOptions.type is |
| // 'imports'. |
| assertEqual('imports', registration.updateViaCache); |
| assertTrue(registration.scope.endsWith( |
| 'registration/scope')); |
| count_event(24); |
| |
| worker = registration.installing; |
| if (worker) { |
| worker.postMessage( |
| 'Registration with scope successful, current ' + |
| 'worker state is installing.'); |
| } |
| worker = registration.waiting; |
| if (worker) { |
| worker.postMessage( |
| 'Registration with scope successful, current ' + |
| 'worker state is waiting.'); |
| } |
| worker = registration.active; |
| if (worker) { |
| worker.postMessage( |
| 'Registration with scope successful, current ' + |
| 'worker state is active.'); |
| } |
| |
| registration.onupdatefound = function (event) { |
| console.log('Got onupdatefound event', |
| event.target.scope); |
| assertTrue(event.target.scope.endsWith( |
| 'registration/scope')); |
| } |
| |
| // Check that the registration has an activated worker after |
| // some time. The delay used here should be long enough for |
| // the service worker to complete activating and have the |
| // state 'activated'. It has to be longer than the combined |
| // delays in the install or activate event handlers. |
| window.setTimeout(function () { |
| // Since these events are asynchronous, the service |
| // worker can be either of these states. |
| console.log( |
| 'Registration active check after timeout', |
| registration); |
| assertNotEqual(null, registration.active); |
| registration.active.postMessage( |
| 'Registration is active after waiting.'); |
| console.log('Registration active', |
| registration.active, 'state:', |
| registration.active.state); |
| assertEqual('activated', registration.active.state); |
| count_event(31); |
| registration.active.onstatechange = function (event) { |
| console.log('Got onstatechange event', |
| event.target.state); |
| } |
| |
| // Repeat a few times to test the 'equivalent job' and |
| // finish job logic. |
| for (let repeated = 0; repeated < 5; repeated++) { |
| registration.update().then(function (registration) { |
| console.log('(Expected) Registration update ' + |
| 'Succeeded:', registration); |
| assertNotEqual(null, registration); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| } |
| |
| registration.unregister() |
| .then(function (success) { |
| console.log('(Expected) unregister success :', |
| success); |
| count_event(37); |
| // Finally, test getRegistration for the unregistered scope. |
| navigator.serviceWorker.getRegistration( |
| 'registration/scope') |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| assertTrue(null == registration || |
| undefined == registration); |
| count_event(38); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| |
| test_claimable_worker(); |
| }, function (error) { |
| console.log('(Unexpected) unregister ' + |
| `${error}`, error); |
| assertIncludes('SecurityError: ', `${error}`); |
| notReached(); |
| }); |
| }, 1000); |
| |
| // Test getRegistration for a non-registered scope. |
| navigator.serviceWorker.getRegistration('/bo/gus') |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| assertTrue(null == registration || |
| undefined == registration); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| |
| // Test getRegistration for a deeper registered scope. |
| navigator.serviceWorker.getRegistration( |
| 'registration/scope/deeper') |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| assertNotEqual(null, registration); |
| assertEqual('imports', registration.updateViaCache); |
| assertTrue(registration.scope.endsWith( |
| 'registration/scope')); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| |
| // Test getRegistration for a shallower registered scope. |
| navigator.serviceWorker.getRegistration('registration') |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| assertTrue(null == registration || |
| undefined == registration); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| |
| // Test getRegistration for a non-registered scope. |
| navigator.serviceWorker.getRegistration() |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| // TODO(b/234659851): Investigate whether this |
| // should return a registration or not, in this case |
| // where there is a registration with a scope. |
| assertTrue(null == registration || |
| undefined == registration); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| |
| // Finally, test getRegistration for a registered scope. |
| navigator.serviceWorker.getRegistration( |
| 'registration/scope') |
| .then(function (registration) { |
| console.log('(Expected) getRegistration Succeeded:', |
| registration); |
| assertNotEqual(null, registration); |
| assertEqual('imports', registration.updateViaCache); |
| assertTrue(registration.scope.endsWith( |
| 'registration/scope')); |
| count_event(); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| }, function (error) { |
| console.log('(Unexpected) :', error); |
| notReached(); |
| }); |
| } |
| |
| assertEqual(undefined, self.clients); |
| |
| console.log('Done starting tests'); |
| setupFinished(); |
| // This delay has to be long enough to guarantee that the test has |
| // finished. |
| window.setTimeout( |
| () => { |
| console.log('Events:', expected_event_count) |
| assertEqual(41, expected_event_count); |
| onEndTest(); |
| }, 7000); |
| |
| </script> |
| </body> |
| |
| </html> |