<!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.
-->
<!--
  This is a basic test of the message event for service workers.
-->

<html>

<head>
    <title>Cobalt Service Worker Message 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)
            }
            return expected_event_count;
        }

        navigator.serviceWorker.onmessage = function (event) {
            console.log('Got onmessage event ', JSON.stringify(event.data));;
            assertTrue(event instanceof MessageEvent);
            assertEqual('[object MessageEvent]', `${event}`);
            assertEqual('[object ServiceWorkerContainer]', `${event.target}`);
            assertEqual('[object Object]', `${event.data}`);
            switch (count_event()) {
                case 3:
                    assertEqual('Foo', event.data.text);
                    assertEqual('BarString', event.data.bar);
                    break;
                case 4:
                    assertEqual('Service Worker received a message from source',
                        event.data.text);
                    assertEqual('{"message":"Registration ready resolved."}',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 5:
                    assertEqual('Service Worker received a message from client',
                        event.data.text);
                    assertEqual('{"message":"Registration ready resolved."}',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 6:
                    assertEqual('Foo', event.data.text);
                    assertEqual('BarString', event.data.bar);
                    break;
                case 7:
                    assertEqual('Service Worker received a message from source',
                        event.data.text);
                    assertEqual('"Controllerchange event received."',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                case 8:
                    assertEqual('Service Worker received a message from client',
                        event.data.text);
                    assertEqual('"Controllerchange event received."',
                        JSON.stringify(event.data.data));
                    assertEqual('[object ExtendableMessageEvent]',
                        event.data.event_type);
                    assertEqual('visible', event.data.visibilityState);
                    assertEqual(true, event.data.focused);
                    break;
                default:
                    notReached();
                    break;
            }

        }

        navigator.serviceWorker.oncontrollerchange = function (event) {
            console.log('Got oncontrollerchange event', event.target);
            count_event(2);
            navigator.serviceWorker.controller.postMessage(
                'Controllerchange event received.');
        }

        navigator.serviceWorker.ready.then(function (
            registration) {
            assertNotEqual(null, registration);
            assertNotEqual(null, registration.active);
            registration.active.postMessage({ message:
                'Registration ready resolved.'});
            count_event(1);
            window.setTimeout(
                () => {
                    registration.unregister()
                        .then(function (success) {
                            console.log('(Expected) unregister success :',
                                success);
                            count_event(9);
                        }, function (error) {
                            console.log('(Unexpected) unregister ' +
                                `${error}`, error);
                            assertIncludes('SecurityError: ', `${error}`);
                            notReached();
                        });
                }, 1000);
        });

        navigator.serviceWorker.register('service_worker_message_test.js', {
            scope: './',
        }).catch(function (error) {
            console.log('(Unexpected) :', error);
            notReached();
        });

        setupFinished();
        // This delay has to be long enough to guarantee that the test has
        // finished.
        window.setTimeout(
            () => {
                console.log('Events:', expected_event_count)
                assertEqual(9, expected_event_count);
                onEndTest();
            }, 2000);

    </script>
</body>

</html>
