blob: 49ef9adeba33ff9cc17ecf396f1faa23a7bc2dee [file] [log] [blame]
<!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() {
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.');
}
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.');
}, 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.
window.setTimeout(function () {
// TODO(b/234659851): Investigate whether this should
// resolve or not, in this case where there already is
// an active worker.
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 after waiting.');
count_event();
});
// 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();
});
}, 500);
// 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();
window.setTimeout(
() => {
console.log('Events:', expected_event_count)
assertEqual(41, expected_event_count);
onEndTest();
}, 3000);
</script>
</body>
</html>