summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/presentation-api/controlling-ua/reconnectToPresentation_success-manual.https.html
blob: a2619042f8fc9325f08c04b4082b634abe295c78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
<!DOCTYPE html>
<meta charset="utf-8">
<title>Reconnect to presentation success manual test</title>
<link rel="author" title="Marius Wessel" href="http://www.fokus.fraunhofer.de">
<link rel="author" title="Louay Bassbouss" href="http://www.fokus.fraunhofer.de">
<link rel="help" href="http://w3c.github.io/presentation-api/#dom-presentationrequest-reconnect">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<style>iframe { display: none; }</style>

<p>Click the button below to start the manual test. Select a presentation device after the selection dialog is prompted.
    The test assumes that at least one presentation device is available. The test passes if a "PASS" result appears.</p>
<button id="startBtn">Start Test</button>
<iframe id="childFrame" src="support/iframe.html"></iframe>

<script>
    let receiverStack;
    add_completion_callback(() => {
        // overwrite a stack written in the test result
        if (receiverStack) {
            document.querySelector('#log pre').textContent = receiverStack;
        }
    });

    // disable timeout for manual tests
    setup({explicit_timeout: true});
    const startBtn = document.getElementById('startBtn');
    const childFrame = document.getElementById('childFrame');

    promise_test(t => {
        const startWatcher = new EventWatcher(t, startBtn, 'click');
        const messageWatcher = new EventWatcher(t, window, 'message');
        const request = new PresentationRequest(presentationUrls);
        let connection, eventWatcher;

        t.add_cleanup(() => {
            if (connection) {
                connection.onconnect = () => { connection.terminate(); }
                if (connection.state === 'closed')
                    request.reconnect(connection.id);
                else
                    connection.terminate();
            }
        });

        const waitForMessage = () => {
            return messageWatcher.wait_for('message').then(evt => {
                return evt.data.type === 'presentation-api' ? evt : waitForMessage();
            });
        };

        // handle a test result received from a nested browsing context
        const parseValue = value => {
            let r;

            // String
            if (r = value.match(/^(\(string\)\s+)?"(.*)"$/))
                return r[2];
            // Object
            else if (r = value.match(/^(\(object\)\s+)?object\s+"\[object\s+(.*)\]"$/))
                return window[r[2]].prototype;
            // undefined
            else if (value === "undefined")
                return undefined;
            // Number, boolean, null
            else {
                if (r = value.match(/^(\(\S+\)\s+)?(\S+)$/)) {
                    try {
                        return JSON.parse(r[2]);
                    } catch(e) {
                        return value;
                    }
                }
                else
                    return value;
            }
        };

        const parseResult = t.step_func(evt => {
            const result = evt.data;
            if (result.test.status === 0)
                return evt;

            receiverStack = result.test.stack;
            const message = result.test.message;
            let r = message.match(/^(assert_.*):\s+(.*)$/);
            if (r) {
                const assertion = r[1];
                const body = r[2];
                let args;
                if (assertion === 'assert_equals') {
                    if (r = body.match(/^((.*)\s+)?expected\s+((\(\S*\)\s+)?(\S+|(\S+\s+)?\".*\"))\s+but\s+got\s+((\(\S*\)\s+)?(\S+|(\S+\s+)?\".*\"))$/))
                        args = [parseValue(r[7]), parseValue(r[3]), r[2]];
                }
                else if (assertion === 'assert_true') {
                    if (r = body.match(/^((.*)\s+)?expected\s+(true|false)\s+got\s+(\S+|(\S+\s+)?\".*\")$/)) {
                        args = [parseValue(r[4]), r[2]];
                    }
                }
                else if (assertion === 'assert_unreached') {
                    if (r = body.match(/^((.*)\s+)?Reached\s+unreachable\s+code$/))
                        args = [r[2]];
                }
                if (args) {
                    window[assertion](args[0], args[1], args[2]);
                    return;
                }
            }
            // default
            assert_unreached('Test result received from a receiving user agent: ' + message + ': ');
        });

        return Promise.all([
            startWatcher.wait_for('click'),
            messageWatcher.wait_for('message')
        ]).then(() => {
            startBtn.disabled = true;
            let presentationId = null;
            return request.start();
        }).then(c => {
            connection = c;
            presentationId = connection.id;

            // No more user input needed, re-enable test timeout
            t.step_timeout(() => {
                t.force_timeout();
                t.done();
            }, 5000);

            eventWatcher = new EventWatcher(t, connection, ['connect', 'close', 'terminate']);

            return Promise.all([
                // Wait for "connect" event
                eventWatcher.wait_for('connect'),
                // Try to reconnect when the connection state is "connecting"
                request.reconnect(presentationId).then(c => {
                    assert_equals(c, connection, 'The promise is resolved with the existing presentation connection.');
                    assert_equals(c.state, "connecting", "The connection state remains 'connecting'.");
                    assert_equals(c.id, presentationId, "The presentation ID is not changed.");
                })
            ]);
        }).then(() => {
            // Try to reconnect when the connection state is "connected"
            return request.reconnect(presentationId);
        }).then(c => {
            assert_equals(c, connection, 'The promise is resolved with the existing presentation connection.');
            assert_equals(c.state, "connected", "The connection state remains 'connected'.");
            assert_equals(c.id, presentationId, "The presentation ID is not changed.");

            // Close connection and wait for "close" event
            connection.close();
            return eventWatcher.wait_for('close');
        }).then(() => {
            // Connection now closed, let's reconnect to it
            return request.reconnect(presentationId);
        }).then(c => {
            // Check the presentation connection in "connecting" state
            assert_equals(c, connection, 'The promise is resolved with the existing presentation connection.');
            connection = c;
            assert_equals(connection.state, "connecting", "The connection state is set to 'connecting'.");
            assert_equals(connection.id, presentationId, "Ids of old and new connections must be equal.");

            return eventWatcher.wait_for('connect');
        }).then(evt => {
            // Check the established presentation connection and its associated "connect" event
            assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
            assert_equals(evt.type, 'connect', 'The event name is "connect".');
            assert_equals(evt.target, connection, 'event.target is the presentation connection.');
            assert_equals(connection.state, 'connected', 'The presentation connection state is set to "connected".');

            // Request an iframe to reconnect the presentation with the current presentation ID
            childFrame.contentWindow.postMessage('reconnect?id=' + presentationId, '*');
            return waitForMessage().then(parseResult);
        }).then(() => {
            // Wait until state of each presentation connection is set to "terminated"
            connection.terminate();
            return Promise.all([ eventWatcher.wait_for('terminate'), waitForMessage().then(parseResult) ]);
        }).then(() => {
            // Try to reconnect to the presentation, while all presentation connection have already been terminated
            return promise_rejects_dom(t, 'NotFoundError', request.reconnect(presentationId),
                'Reconnecting to a terminated presentation rejects a promise with a "NotFoundError" exception.');
        });
    });
</script>