<!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>
