blob: 7521b4fd23c8e3362d4e576b0f1b4253f6c2a4fc [file] [log] [blame]
<!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(t, 'NotFoundError', request.reconnect(presentationId),
'Reconnecting to a terminated presentation rejects a promise with a "NotFoundError" exception.');
});
});
</script>