Update web-platform-tests to revision a46616a5b18e83587ddbbed756c7b96cbb4b015d

This commit is contained in:
Josh Matthews 2017-06-19 19:07:14 -04:00 committed by Ms2ger
parent 3f07cfec7c
commit 578498ba24
4001 changed files with 159517 additions and 30260 deletions

View file

@ -14,20 +14,20 @@
// prevent the default timeout
setup({explicit_timeout: true});
var notice = document.getElementById('notice');
const notice = document.getElementById('notice');
promise_test(function(t) {
promise_test(t => {
// clean up the instruction notice when the test ends
t.add_cleanup(function() {
notice.parentNode.removeChild(notice);
t.add_cleanup(() => {
notice.parentNode.removeChild(notice);
});
// initialize a presentation request
var request = new PresentationRequest(presentationUrls);
const request = new PresentationRequest(presentationUrls);
var availability, previousState, timeout;
let availability, previousState, timeout;
function wait() {
const wait = () => {
notice.textContent = 'Please wait for a moment... (It might take long time)';
// set timeout to observe the presentation availability
@ -35,9 +35,9 @@
t.force_timeout();
t.done();
}, 90000);
}
};
function setup() {
const setup = () => {
// save the current value of the presentation availability
previousState = availability.value;
@ -45,34 +45,45 @@
notice.textContent = 'Please make your presentation displays '
+ (previousState ? 'unavailable' : 'available')
+ ' and click this button: ';
var button = document.createElement('button');
const button = document.createElement('button');
button.textContent = 'Start Monitoring';
button.onclick = wait;
notice.appendChild(button);
}
};
var check = t.step_func(function(a) {
// check the event and its attributes
const checkEvent = evt => {
clearTimeout(timeout);
timeout = undefined;
assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
assert_equals(evt.type, 'change', 'The event name is "change".');
assert_equals(evt.target, availability, 'event.target is the presentation availability.');
assert_not_equals(previousState, availability.value, 'Value of the presentation availability is changed.');
setup();
};
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
// check the change of PresentationAvailability.value twice; "true to false" and "false to true"
return request.getAvailability().then(a => {
availability = a;
setup();
availability.onchange = t.step_func(function(evt) {
clearTimeout(timeout);
timeout = undefined;
// check the event and its attributes
assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
assert_equals(evt.type, 'change', 'The event name is "change".');
assert_equals(evt.target, availability, 'event.target is the presentation availability.');
assert_not_equals(previousState, availability.value, 'Value of the presentation availability is changed.');
setup();
});
// wait until a "change" event is fired twice
var eventWatcher = new EventWatcher(t, availability, 'change');
return eventWatcher.wait_for(['change', 'change']);
return watchEvent(availability, eventWatcher, 'change')
.then(checkEvent)
.then(() => { return eventWatcher.wait_for('change'); })
.then(checkEvent);
});
// check the change of PresentationAvailability.value twice; "true to false" and "false to true"
return request.getAvailability().then(check);
});
</script>

View file

@ -0,0 +1,145 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Closing a PresentationConnection</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="He Yue" href="mailto:yue.he@intel.com">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="https://w3c.github.io/presentation-api/#closing-a-presentationconnection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<script src="support/stash.js"></script>
<h2>Description</h2>
<p>
This test validates that after connection close,<br/>
the connection state is set closed,<br/>
the onclose EventHandler is triggered.
</p>
<br/>
<p>Click the button below to start the test.</p>
<button id="presentBtn" >Start Presentation Test</button>
<script>
setup({explicit_timeout: true});
const presentBtn = document.getElementById('presentBtn');
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const request = new PresentationRequest(presentationUrls);
const stash = new Stash(stashIds.toController, stashIds.toReceiver);
let connection, eventWatcher;
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
stash.stop();
});
const checkCloseEvent = evt => {
assert_true(evt instanceof PresentationConnectionCloseEvent, 'An event using PresentationConnectionCloseEvent is fired.');
assert_true(evt.isTrusted, 'The event is a trusted event.');
assert_false(evt.bubbles, 'The event does not bubbles.');
assert_false(evt.cancelable, 'The event is not cancelable.');
assert_equals(evt.type, 'close', 'The event name is "close".');
assert_equals(evt.target, connection, 'event.target is the presentation connection.');
assert_equals(connection.state, 'closed', 'State of the presentation connection is "closed".');
assert_equals(evt.reason, 'closed', 'The reason for closing the presentation connection is "closed".');
};
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
const waitForEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.race([ watchHandler, watcher.wait_for(type) ]);
};
return Promise.all([
clickWatcher.wait_for('click'),
stash.init()
]).then(() => {
presentBtn.disabled = true;
return request.start();
}).then(c => {
// Enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 10000);
connection = c;
eventWatcher = new EventWatcher(t, connection, ['connect', 'close', 'terminate']);
// Step 1: close the presentation connection in "connecting" state
connection.close();
return Promise.race([
new Promise((_, reject) => {
t.step_timeout(() => { reject('The presentation connection in "connecting" state was not closed successfully.'); }, 3000);
}),
watchEvent(connection, eventWatcher, 'close')
]);
}).then(evt => {
checkCloseEvent(evt);
// Step 2: close the presentation connection in "connected" state
return request.reconnect(connection.id);
}).then(() => {
return eventWatcher.wait_for('connect');
}).then(() => {
connection.close();
return watchEvent(connection, eventWatcher, 'close');
}).then(evt => {
checkCloseEvent(evt);
// Step 3: check a connection closed by the receiving user agent
return request.reconnect(connection.id);
}).then(() => {
return eventWatcher.wait_for('connect');
}).then(() => {
return Promise.all([ stash.send('close'), watchEvent(connection, eventWatcher, 'close') ]);
}).then(results => {
checkCloseEvent(results[1]);
// Step 4: close the presentation connection in "closed" state (nothing should happen)
const closeWatcher = new EventWatcher(t, connection, 'close');
connection.close();
return Promise.race([
new Promise(resolve => { t.step_timeout(resolve, 1000); }),
waitForEvent(connection, closeWatcher, 'close').then(() => {
assert_unreached('Invoking PresentationConnection.close() in the "closed" state causes nothing.'); })
]);
}).then(() => {
// Step 5: close the presentation connection in "terminated" state (nothing should happen)
return request.reconnect(connection.id);
}).then(() => {
return eventWatcher.wait_for('connect');
}).then(() => {
connection.terminate();
return eventWatcher.wait_for('terminate');
}).then(() => {
const closeWatcher = new EventWatcher(t, connection, 'close');
connection.close();
return Promise.race([
new Promise(resolve => { t.step_timeout(resolve, 1000); }),
waitForEvent(connection, closeWatcher, 'close').then(() => {
assert_unreached('Invoking PresentationConnection.close() in the "terminated" state causes nothing.'); })
]);
});
});
</script>

View file

@ -1,48 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>PresentationConnection.onclose</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="He Yue" href="mailto:yue.he@intel.com">
<link rel="help" href="http://w3c.github.io/presentation-api/#interface-presentationconnection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<h2>Description</h2>
<p>
This test validates that after connection close,<br/>
the connection state is set closed,<br/>
the onclose EventHandler is triggered.
</p>
<br/>
<p>Click the button below to start the test.</p>
<button id="presentBtn" onclick="startPresentation()">Start Presentation Test</button>
<script>
setup({explicit_timeout: true});
var startPresentation = function () {
document.getElementById('presentBtn').disabled = true;
async_test(function(t) {
var request = new PresentationRequest(presentationUrls);
request.start()
.then(function(connection) {
// Enable timeout again, cause no user action is needed from here.
t.step_timeout(function() {
t.force_timeout();
t.done();
}, 5000);
assert_true(connection instanceof PresentationConnection, 'the connection is setup');
connection.onclose = t.step_func_done(function(evt) {
assert_equals(evt.type, "close");
assert_equals(connection.state, "closed");
});
connection.close();
})
.catch(function(ex) {
assert_unreached(ex.name + ":" + ex.message);
});
}, "the onclose is fired and the connection state is closed.");
}
</script>

View file

@ -0,0 +1,72 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Establishing a presentation connection</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="He Yue" href="mailto:yue.he@intel.com">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="https://w3c.github.io/presentation-api/#establishing-a-presentation-connection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<h2>Description</h2>
<p>
This test validates that after connection starts,<br/>
the onconnect EventHandler is triggered and connection state is connected.
</p>
<br/>
<p>Click the button below to start the test.</p>
<button id="presentBtn">Start Presentation Test</button>
<script>
setup({explicit_timeout: true});
const presentBtn = document.getElementById('presentBtn');
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const request = new PresentationRequest(presentationUrls);
let connection;
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
});
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
return clickWatcher.wait_for('click').then(() => {
presentBtn.disabled = true;
return request.start();
}).then(c => {
// Enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 5000);
connection = c;
const eventWatcher = new EventWatcher(t, connection, 'connect');
return watchEvent(connection, eventWatcher, 'connect');
}).then(evt => {
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".');
});
});
</script>

View file

@ -1,46 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>PresentationConnection.onconnect</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="He Yue" href="mailto:yue.he@intel.com">
<link rel="help" href="http://w3c.github.io/presentation-api/#interface-presentationconnection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<h2>Description</h2>
<p>
This test validates that after connection starts,<br/>
the onconnect EventHandler is triggered and connection state is connected.
</p>
<br/>
<p>Click the button below to start the test.</p>
<button id="presentBtn" onclick="startPresentation()">Start Presentation Test</button>
<script>
setup({explicit_timeout: true});
var startPresentation = function () {
document.getElementById('presentBtn').disabled = true;
async_test(function(t) {
var request = new PresentationRequest(presentationUrls);
request.start()
.then(function(connection) {
// Enable timeout again, cause no user action is needed from here.
t.step_timeout(function() {
t.force_timeout();
t.done();
}, 5000);
assert_true(connection instanceof PresentationConnection);
connection.onconnect = t.step_func_done(function() {
assert_equals(connection.state, "connected");
connection.terminate();
});
})
.catch(function(ex) {
assert_unreached(ex.name + ":" + ex.message);
});
}, "the onconnect is fired and the connection state is connected");
}
</script>

View file

@ -36,103 +36,109 @@
return !!p && !!q && p.every((item, index) => { return item === q[index]; });
};
presentBtn.onclick = () => {
presentBtn.disabled = true;
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const request = new PresentationRequest(presentationUrls);
const stash = new Stash(stashIds.toController, stashIds.toReceiver);
let connection, watcher, eventWatcher;
promise_test(t => {
let connection, watcher, eventWatcher;
const request = new PresentationRequest(presentationUrls);
const checkEvent = event => {
assert_true(event.isTrusted, 'a trusted event is fired');
assert_true(event instanceof MessageEvent, 'The event uses the MessageEvent interface');
assert_false(event.bubbles, 'the event does not bubble');
assert_false(event.cancelable, 'the event is not cancelable');
};
const checkEvent = event => {
assert_true(event.isTrusted, 'a trusted event is fired');
assert_true(event instanceof MessageEvent, 'The event uses the MessageEvent interface');
assert_false(event.bubbles, 'the event does not bubble');
assert_false(event.cancelable, 'the event is not cancelable');
};
t.add_cleanup(() => {
if (connection) {
if (connection.state === 'connecting') {
connection.onconnect = event => {
connection.terminate();
};
}
else if (connection.state === 'connected')
connection.terminate();
else if (connection.state === 'closed') {
request.reconnect(connection.id).then(c => {
c.terminate();
});
}
}
const notice = document.getElementById('notice');
notice.parentNode.removeChild(notice);
stash.stop();
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return request.start().then(c => {
connection = c;
assert_equals(connection.state, 'connecting', 'the initial state of the presentation connection is "connecting"');
assert_equals(connection.binaryType, 'arraybuffer', 'the default value of binaryType is "arraybuffer"');
// enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 5000);
watcher = new EventWatcher(t, connection, 'connect');
return watcher.wait_for('connect');
}).then(() => {
return stash.init();
}).then(() => {
eventWatcher = new EventWatcher(t, connection, 'message');
// Tell receiving page to start sending messages, and wait for first message
return Promise.all([
stash.send('onmessage'),
eventWatcher.wait_for('message')
]).then(results => results[1]);
}).then(event => {
checkEvent(event);
assert_equals(event.data, message1, 'receive a string correctly');
return eventWatcher.wait_for('message');
}).then(event => {
checkEvent(event);
assert_equals(event.data, message2, 'receive a string correctly');
return eventWatcher.wait_for('message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message3), 'receive an ArrayBuffer correctly (originally a Blob at a receiving user agent)');
return eventWatcher.wait_for('message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message4), 'receive an ArrayBuffer correctly (originally an ArrayBuffer at a receiving user agent)');
return eventWatcher.wait_for('message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message5), 'receive an ArrayBuffer correctly (originally an ArrayBufferView at a receiving user agent)');
connection.binaryType = 'blob';
return Promise.all([
stash.send('blob'),
eventWatcher.wait_for('message')
]).then(results => results[1]);
}).then(event => {
assert_true(event.data instanceof Blob, 'receive binary data as Blob');
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = resolve;
reader.onerror = reject;
reader.readAsArrayBuffer(event.data);
});
}).then(event => {
assert_true(compare(event.target.result, message5), 'receive a Blob correctly');
connection.terminate();
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
const notice = document.getElementById('notice');
notice.parentNode.removeChild(notice);
stash.stop();
});
};
return Promise.all([
clickWatcher.wait_for('click'),
stash.init()
]).then(() => {
presentBtn.disabled = true;
return request.start();
}).then(c => {
connection = c;
assert_equals(connection.state, 'connecting', 'the initial state of the presentation connection is "connecting"');
assert_equals(connection.binaryType, 'arraybuffer', 'the default value of binaryType is "arraybuffer"');
// enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 5000);
watcher = new EventWatcher(t, connection, 'connect');
return watcher.wait_for('connect');
}).then(() => {
return stash.init();
}).then(() => {
eventWatcher = new EventWatcher(t, connection, 'message');
// Tell receiving page to start sending messages, and wait for first message
return Promise.all([
stash.send('onmessage'),
watchEvent(connection, eventWatcher, 'message')
]).then(results => results[1]);
}).then(event => {
checkEvent(event);
assert_equals(event.data, message1, 'receive a string correctly');
return watchEvent(connection, eventWatcher, 'message');
}).then(event => {
checkEvent(event);
assert_equals(event.data, message2, 'receive a string correctly');
return watchEvent(connection, eventWatcher, 'message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message3), 'receive an ArrayBuffer correctly (originally a Blob at a receiving user agent)');
return watchEvent(connection, eventWatcher, 'message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message4), 'receive an ArrayBuffer correctly (originally an ArrayBuffer at a receiving user agent)');
return watchEvent(connection, eventWatcher, 'message');
}).then(event => {
checkEvent(event);
assert_true(event.data instanceof ArrayBuffer, 'receive binary data as ArrayBuffer');
assert_true(compare(event.data, message5), 'receive an ArrayBuffer correctly (originally an ArrayBufferView at a receiving user agent)');
connection.binaryType = 'blob';
return Promise.all([
stash.send('blob'),
watchEvent(connection, eventWatcher, 'message')
]).then(results => results[1]);
}).then(event => {
assert_true(event.data instanceof Blob, 'receive binary data as Blob');
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = resolve;
reader.onerror = reject;
reader.readAsArrayBuffer(event.data);
});
}).then(event => {
assert_true(compare(event.target.result, message5), 'receive a Blob correctly');
connection.terminate();
});
});
</script>

View file

@ -0,0 +1,157 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Terminating a presentation in a controlling browsing context</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="Chunyan Wang" href="mailto:chunyanx.wang@intel.com">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="https://w3c.github.io/presentation-api/#terminating-a-presentation-in-a-controlling-browsing-context">
<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 and select the available presentation display, to start the manual test. The test passes if a "PASS" result appears.<br>
This test asks you to click the button twice, unless the test fails.<br>
</p>
<button id="presentBtn">Start Presentation Test</button>
<iframe id="childFrame" src="support/iframe.html"></iframe>
<script>
setup({explicit_timeout: true});
const presentBtn = document.getElementById('presentBtn');
const childFrame = document.getElementById('childFrame');
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const messageWatcher = new EventWatcher(t, window, 'message');
const request = new PresentationRequest(presentationUrls);
let connection, eventWatcher, timeout;
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
});
const startTimeout = () => {
timeout = t.step_timeout(() => {
t.force_timeout();
t.done();
}, 10000);
};
const checkTerminateEvent = evt => {
assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
assert_equals(evt.type, 'terminate', 'The event name is "terminate".');
assert_equals(evt.target, connection, 'event.target is the presentation connection.');
assert_equals(connection.state, 'terminated', 'State of the presentation connection is "terminated".');
};
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
const waitForEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
return Promise.race([ watchHandler, watcher.wait_for(type) ]);
};
return Promise.all([
clickWatcher.wait_for('click'),
messageWatcher.wait_for('message')
]).then(() => {
presentBtn.disabled = true;
return request.start();
}).then(c => {
startTimeout();
connection = c;
eventWatcher = new EventWatcher(t, connection, 'terminate');
// Step 1: terminate the presentation when the presentation connection is in "connecting" state
connection.terminate();
return Promise.race([
new Promise((_, reject) => {
t.step_timeout(() => { reject('The presentation is not terminated successfully when the presentation connection in "connecting" state.'); }, 3000);
}),
watchEvent(connection, eventWatcher, 'terminate')
]);
}).then(evt => {
checkTerminateEvent(evt);
// Step 2: terminate the presentation when the presentation connection is in "closed" state (nothing should happen)
presentBtn.textContent = 'Continue Presentation Test';
presentBtn.disabled = false;
clearTimeout(timeout);
return clickWatcher.wait_for('click');
}).then(() => {
return request.start();
}).then(c => {
startTimeout();
connection = c;
eventWatcher = new EventWatcher(t, connection, ['connect', 'close', 'terminate']);
return eventWatcher.wait_for('connect');
}).then(() => {
connection.close();
return eventWatcher.wait_for('close');
}).then(() => {
const terminateWatcher = new EventWatcher(t, connection, 'terminate');
connection.terminate();
return Promise.race([
new Promise(resolve => { t.step_timeout(resolve, 1000); }),
waitForEvent(connection, terminateWatcher, 'terminate').then(() => {
assert_unreached('Invoking PresentationConnection.terminate() in the "closed" state causes nothing.'); })
]);
}).then(() => {
// Step 3: terminate the presentation when the presentation connection is in "connected" state;
// this step also checks an event fired at another presentation connection in a nested browsing context
return request.reconnect(connection.id);
}).then(() => {
return eventWatcher.wait_for('connect');
}).then(() => {
childFrame.contentWindow.postMessage('terminate?id=' + connection.id, '*');
return messageWatcher.wait_for('message')
}).then(() => {
connection.terminate();
return Promise.race([
new Promise((_, reject) => {
t.step_timeout(() => { reject('The presentation is not terminated successfully when the presentation connection in "connected" state.'); }, 3000);
}),
Promise.all([
watchEvent(connection, eventWatcher, 'terminate'),
messageWatcher.wait_for('message')
])
]);
}).then(results => {
checkTerminateEvent(results[0]);
const evt = results[1].data;
assert_true(evt.isSimpleEvent, 'A simple event is fired in a nested browsing context.');
assert_equals(evt.type, 'terminate', 'The event name is "terminate".');
assert_true(evt.checkConnection, 'event.target is the presentation connection.');
assert_equals(evt.state, 'terminated', 'State of the presentation connection is "terminated".');
// Step 4: terminate the presentation when the presentation connection is in "terminated" state (nothing should happen)
const terminateWatcher = new EventWatcher(t, connection, 'terminate');
connection.terminate();
return Promise.race([
new Promise(resolve => { t.step_timeout(resolve, 1000); }),
waitForEvent(connection, terminateWatcher, 'terminate').then(() => {
assert_unreached('Invoking PresentationConnection.terminate() in the "terminated" state causes nothing.'); })
]);
});
});
</script>

View file

@ -1,54 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>PresentationConnection.onterminate</title>
<link rel="author" title="Intel" href="http://www.intel.com">
<link rel="author" title="Chunyan Wang" href="mailto:chunyanx.wang@intel.com">
<link rel="help" href="http://w3c.github.io/presentation-api/#starting-a-presentation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<h2>Description</h2>
<p>
This test validates that after connection terminate,<br/>
the connection state is set terminated,<br/>
the onterminate EventHandler is triggered.
</p>
<br/>
<p>Click the button below to start the test.</p>
<button id="presentBtn" onclick="startPresentation()">Start Presentation Test</button>
<script>
setup({explicit_timeout: true});
var startPresentation = function () {
document.getElementById('presentBtn').disabled = true;
async_test(function(t) {
var request = new PresentationRequest(presentationUrls);
request.start()
.then(function(connection) {
// Enable timeout again, cause no user action is needed from here.
t.step_timeout(function() {
t.force_timeout();
t.done();
}, 5000);
assert_true(connection instanceof PresentationConnection);
connection.onconnect = t.step_func(function(evt) {
assert_equals(connection.state, "connected");
connection.terminate();
});
connection.onterminate = t.step_func_done(function(evt) {
assert_equals(evt.type, "terminate");
assert_equals(connection.state, "terminated");
});
connection.onclose = t.step_func_done(function(evt) {
assert_unreached("Wrong, the onclose shouldn't be triggered!");
});
})
.catch(function(ex) {
assert_unreached(ex.name + ":" + ex.message);
});
}, "the onterminate is fired and the connection state is terminated");
}
</script>

View file

@ -37,92 +37,89 @@
}, '');
}
presentBtn.onclick = () => {
presentBtn.disabled = true;
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const stash = new Stash(stashIds.toController, stashIds.toReceiver);
const request = new PresentationRequest(presentationUrls);
let connection, watcher;
promise_test(t => {
let connection, watcher;
const request = new PresentationRequest(presentationUrls);
t.add_cleanup(() => {
if (connection) {
if (connection.state === 'connected')
connection.terminate();
else if (connection.state === 'closed') {
request.reconnect(connection.id).then(c => {
c.terminate();
});
}
}
const notice = document.getElementById('notice');
notice.parentNode.removeChild(notice);
stash.stop();
});
return request.start().then(c => {
connection = c;
// send data in "connecting" state (throws an exception)
assert_equals(connection.state, 'connecting', 'the initial state of the presentation connection is "connecting"');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "connecting"');
// enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 10000);
watcher = new EventWatcher(t, connection, ['connect', 'close']);
return watcher.wait_for('connect');
}).then(() => {
return stash.init();
}).then(() => {
return Promise.all([ stash.send('send'), stash.receive() ]);
}).then(results => {
// send messages
connection.send(message1); // string
connection.send(message2); // string
connection.send(new Blob([message3])); // Blob
connection.send(message4.buffer); // ArrayBuffer
connection.send(message5); // ArrayBufferView
return stash.receive();
}).then(stash => {
// verify messages
const results = JSON.parse(stash);
assert_true(!!results[0] && results[0].type === 'text' && results[0].data === message1, 'send a string correctly');
assert_true(!!results[1] && results[1].type === 'text' && results[1].data === message2, 'send a string correctly');
assert_true(!!results[2] && results[2].type === 'binary' && results[2].data === toText(message3), 'send a Blob correctly');
assert_true(!!results[3] && results[3].type === 'binary' && results[3].data === toText(message4), 'send a ArrayBuffer correctly');
assert_true(!!results[4] && results[4].type === 'binary' && results[4].data === toText(message5), 'send a ArrayBufferView correctly');
// send data in "closed" state (throws an exception)
connection.close();
return watcher.wait_for('close');
}).then(() => {
assert_equals(connection.state, 'closed', 'the state is set to "closed" when the presentation connection is closed');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "closed"');
// reconnect and terminate the connection
return request.reconnect(connection.id);
}).then(c => {
connection = c;
watcher = new EventWatcher(t, connection, ['connect', 'terminate']);
return watcher.wait_for('connect');
}).then(() => {
// send data in "terminated" state (throws an exception)
connection.terminate();
return watcher.wait_for('terminate');
}).then(() => {
assert_equals(connection.state, 'terminated', 'the state is set to "terminated" when the presentation connection is terminated');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "terminated"');
});
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
const notice = document.getElementById('notice');
notice.parentNode.removeChild(notice);
stash.stop();
});
};
return clickWatcher.wait_for('click').then(() => {
presentBtn.disabled = true;
return request.start();
}).then(c => {
connection = c;
// send data in "connecting" state (throws an exception)
assert_equals(connection.state, 'connecting', 'the initial state of the presentation connection is "connecting"');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "connecting"');
// enable timeout again, cause no user action is needed from here.
t.step_timeout(() => {
t.force_timeout();
t.done();
}, 10000);
watcher = new EventWatcher(t, connection, ['connect', 'close', 'terminate']);
return watcher.wait_for('connect');
}).then(() => {
return stash.init();
}).then(() => {
return Promise.all([ stash.send('send'), stash.receive() ]);
}).then(results => {
// send messages
connection.send(message1); // string
connection.send(message2); // string
connection.send(new Blob([message3])); // Blob
connection.send(message4.buffer); // ArrayBuffer
connection.send(message5); // ArrayBufferView
return stash.receive();
}).then(stash => {
// verify messages
const results = JSON.parse(stash);
assert_true(!!results[0] && results[0].type === 'text' && results[0].data === message1, 'send a string correctly');
assert_true(!!results[1] && results[1].type === 'text' && results[1].data === message2, 'send a string correctly');
assert_true(!!results[2] && results[2].type === 'binary' && results[2].data === toText(message3), 'send a Blob correctly');
assert_true(!!results[3] && results[3].type === 'binary' && results[3].data === toText(message4), 'send a ArrayBuffer correctly');
assert_true(!!results[4] && results[4].type === 'binary' && results[4].data === toText(message5), 'send a ArrayBufferView correctly');
// send data in "closed" state (throws an exception)
connection.close();
return watcher.wait_for('close');
}).then(() => {
assert_equals(connection.state, 'closed', 'the state is set to "closed" when the presentation connection is closed');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "closed"');
// reconnect and terminate the connection
return request.reconnect(connection.id);
}).then(() => {
return watcher.wait_for('connect');
}).then(() => {
// send data in "terminated" state (throws an exception)
connection.terminate();
return watcher.wait_for('terminate');
}).then(() => {
assert_equals(connection.state, 'terminated', 'the state is set to "terminated" when the presentation connection is terminated');
assert_throws('InvalidStateError', () => {
connection.send('');
}, 'an InvalidStateError is thrown if the state is "terminated"');
});
});
</script>

View file

@ -1,6 +1,6 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>PresentationRequest.onconnectionavailable (manual test)</title>
<title>Firing a connectionavailable event at a controlling user agent</title>
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs">
<link rel="help" href="https://w3c.github.io/presentation-api/#starting-a-presentation">
<script src="/resources/testharness.js"></script>
@ -17,43 +17,67 @@
// ----------
// DOM Object
// ----------
var presentBtn = document.getElementById("presentBtn");
const presentBtn = document.getElementById('presentBtn');
// --------------------------------------------------------------------------
// Start New PresentationRequest.onconnectionavailable Test (success) - begin
// --------------------------------------------------------------------------
var startPresentation = function () {
presentBtn.disabled = true;
promise_test(function (t) {
var connection;
t.add_cleanup(function() {
if(connection)
connection.terminate();
});
promise_test(t => {
const clickWatcher = new EventWatcher(t, presentBtn, 'click');
const request = new PresentationRequest(presentationUrls);
let connection;
// Note: During starting a presentation, the connectionavailable event is fired (step 20)
// after the promise P is resolved (step 19).
return new Promise(function(resolve, reject) {
var request = new PresentationRequest(presentationUrls);
request.onconnectionavailable = function (evt) {
resolve(evt.connection);
};
// This test fails if request.onconnectionavailable is not invoked although the presentation is started successfully
// or the presentation fails to be started
request.start().then(function(c) {
connection = c;
t.step_timeout(function() { assert_unreached('The connectionavailable event was not fired.'); }, 5000);
}, reject);
}).then(function(c) {
connection = c;
assert_equals(connection.state, 'connecting', 'The initial state of the presentation connection is "connecting".');
assert_true(!!connection.id, 'The connection ID is set.');
assert_true(typeof connection.id === 'string', 'The connection ID is a string.');
assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.');
t.add_cleanup(() => {
if (connection) {
connection.onconnect = () => { connection.terminate(); };
if (connection.state === 'closed')
request.reconnect(connection.id);
else
connection.terminate();
}
});
const watchEvent = (obj, watcher, type) => {
const watchHandler = new Promise(resolve => {
obj['on' + type] = evt => { resolve(evt); };
});
}, 'The connectionavailable event was fired successfully.');
}
presentBtn.onclick = startPresentation;
return Promise.all([ watchHandler, watcher.wait_for(type) ]).then(results => {
assert_equals(results[0], results[1], 'Both on' + type + ' and addEventListener pass the same event object.');
return results[0];
});
};
return clickWatcher.wait_for('click').then(() => {
presentBtn.disabled = true;
// Note: During starting a presentation, the connectionavailable event is fired (step 9)
// after the promise P is resolved (step 8).
return request.start();
}).then(c => {
connection = c;
assert_equals(connection.state, 'connecting', 'The initial state of the presentation connection is "connecting".');
assert_true(!!connection.id, 'The connection ID is set.');
assert_true(typeof connection.id === 'string', 'The connection ID is a string.');
assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.');
const eventWatcher = new EventWatcher(t, request, 'connectionavailable');
const timeout = new Promise((_, reject) => {
// This test fails if request.onconnectionavailable is not invoked although the presentation is started successfully
// or the presentation fails to be started.
t.step_timeout(() => { reject('The connectionavailable event was not fired (timeout).'); }, 5000);}
);
return Promise.race([ watchEvent(request, eventWatcher, 'connectionavailable'), timeout ]);
}).then(evt => {
assert_true(evt instanceof PresentationConnectionAvailableEvent, 'An event using PresentationConnectionAvailableEvent is fired.');
assert_true(evt.isTrusted, 'The event is a trusted event.');
assert_false(evt.bubbles, 'The event does not bubbles.');
assert_false(evt.cancelable, 'The event is not cancelable.');
assert_equals(evt.type, 'connectionavailable', 'The event name is "connectionavailable".');
assert_equals(evt.target, request, 'event.target is the presentation request.');
assert_true(evt.connection instanceof PresentationConnection, 'event.connection is a presentation connection.');
assert_equals(evt.connection, connection, 'event.connection is set to the presentation which the promise is resolved with.');
});
});
// ------------------------------------------------------------------------
// Start New PresentationRequest.onconnectionavailable Test (success) - end
// ------------------------------------------------------------------------

View file

@ -1,43 +1,24 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Presentation API PresentationRequest for Controlling User Agent (Success)</title>
<title>Constructing a PresentationRequest</title>
<link rel="author" title="Franck William Taffo" href="http://www.fokus.fraunhofer.de">
<link rel="help" href="http://w3c.github.io/presentation-api/#dfn-controlling-user-agent">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="http://w3c.github.io/presentation-api/#constructing-a-presentationrequest">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {
try {
var request = new PresentationRequest('presentation.html');
assert_true(request instanceof PresentationRequest);
}
catch (ex) {
assert_unreached('PresentationRequest constructor threw an unexpected exception "' + ex.name + '"');
}
}, 'Call PresentationRequest constructor with a valid relative presentation URL. No Exception expected.');
test(() => {
let request = new PresentationRequest('presentation.html');
assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with a relative presentation URL is constructed successfully.');
test(function() {
try {
var request = new PresentationRequest('http://example.org/');
assert_true(request instanceof PresentationRequest);
}
catch (ex) {
assert_unreached('PresentationRequest constructor threw an unexpected exception "' + ex.name + '"');
}
}, 'Call PresentationRequest constructor with a valid absolute presentation URL. No Exception expected.');
test(function() {
try {
var request = new PresentationRequest([
'presentation.html',
'http://example.org/presentation/'
]);
assert_true(request instanceof PresentationRequest);
}
catch (ex) {
assert_unreached('PresentationRequest constructor threw an unexpected exception "' + ex.name + '"');
}
}, 'Call PresentationRequest constructor with a set of valid presentation URLs. No Exception expected.');
request = new PresentationRequest('https://example.org/');
assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an absolute presentation URL is constructed successfully.');
request = new PresentationRequest([
'presentation.html',
'https://example.org/presentation/'
]);
assert_true(request instanceof PresentationRequest, 'An instance of PresentationRequest with an array of presentation URLs is constructed successfully.');
});
</script>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Setting a default presentation request</title>
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs">
<link rel="help" href="http://w3c.github.io/presentation-api/#controlling-user-agent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(() => {
assert_equals(navigator.presentation.defaultRequest, null, 'The initial value of the default presentation request is null.');
const request = new PresentationRequest('https://example.org/');
navigator.presentation.defaultRequest = request;
assert_equals(navigator.presentation.defaultRequest, request, 'The default presentation request is set to an instance of PresentationRequest.');
assert_throws(new TypeError(), () => {
navigator.presentation.defaultRequest = {};
}, 'The default presentation request cannot be set to any value but an instance of PresentationRequest or null.');
navigator.presentation.defaultRequest = null;
assert_equals(navigator.presentation.defaultRequest, null, 'The default presentation request is set to null.');
});
</script>

View file

@ -16,33 +16,46 @@
// Presentation Availability Tests - begin
// ---------------------------------------
promise_test(function(t) {
var availability;
promise_test(t => {
let availability;
var request = new PresentationRequest(presentationUrls);
const request = new PresentationRequest(presentationUrls);
assert_true(request instanceof PresentationRequest, 'The request is an instance of PresentationRequest.');
var promise = request.getAvailability();
const promise = request.getAvailability();
assert_equals(promise, request.getAvailability(), 'If the PresentationRequest object has an unsettled Promise, getAvailability returns that Promise.');
function catchNotSupported(err) {
assert_equals(err.name, 'NotSupportedError', 'getAvailability() rejects a Promise with a NotSupportedError exception, if the browser can find presentation displays only when starting a connection.')
}
return promise.then(function (a) {
return promise.then(a => {
availability = a;
assert_true(availability instanceof PresentationAvailability, 'The promise is resolved with an instance of PresentationAvailability.');
assert_equals(typeof availability.value, 'boolean', 'The availability has an boolean value.');
assert_true(availability.value, 'The availability value is true when any presentation display is available.');
var newPromise = request.getAvailability();
assert_not_equals(promise, newPromise, 'If the Promise from a previous call to getAvailability has already been settled, getAvailability returns a new Promise.');
// The value of the presentation availability object is set to false, when the object is newly created.
const waitForChange = () => {
const eventWatcher = new EventWatcher(t, availability, 'change');
return eventWatcher.wait_for('change');
};
return newPromise.then(function (newAvailability) {
assert_equals(availability, newAvailability, 'Promises from a PresentationRequest\'s getAvailability are resolved with the same PresentationAvailability object.');
return (availability.value ? Promise.resolve() : waitForChange()).then(() => {
assert_true(availability.value, 'The availability value is true when any presentation display is available.');
const request2 = new PresentationRequest('https://example.com');
return request2.getAvailability();
}).then(a => {
assert_not_equals(availability, a, 'A presentation availability object is newly created if the presentation request has a newly added presentation URLs.');
const newPromise = request.getAvailability();
assert_not_equals(promise, newPromise, 'If the Promise from a previous call to getAvailability has already been settled, getAvailability returns a new Promise.');
return newPromise.then(newAvailability => {
assert_equals(availability, newAvailability, 'Promises from a PresentationRequest\'s getAvailability are resolved with the same PresentationAvailability object.');
}, catchNotSupported);
}, catchNotSupported);
}, catchNotSupported);
});
</script>

View file

@ -7,48 +7,179 @@
<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});
var startBtn = document.getElementById("startBtn");
startBtn.onclick = function () {
startBtn.disabled = true;
promise_test(function (t) {
var request = new PresentationRequest(presentationUrls);
var presentationId = null;
var connection;
const startBtn = document.getElementById('startBtn');
const childFrame = document.getElementById('childFrame');
t.add_cleanup(function() {
if(connection)
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();
});
return request.start().then(function (c) {
connection = c;
presentationId = connection.id;
// No more user input needed, re-enable test timeout
t.step_timeout(function () {
t.force_timeout();
t.done();
}, 5000);
// Close connection and wait for "close" event
connection.close();
var eventWatcher = new EventWatcher(t, connection, 'close');
return eventWatcher.wait_for('close');
}).then(function () {
// Connection now closed, let's reconnect to it
return request.reconnect(presentationId);
}).then(function (c) {
connection = c;
assert_equals(connection.state, "connecting", "connection should be in 'connecting' state");
assert_equals(connection.id, presentationId, "Ids of old and new connections must be equal");
});
}
});
};
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>

View file

@ -2,9 +2,23 @@
<meta charset="utf-8">
<title>Presentation API - controlling ua - sandboxing</title>
<link rel="author" title="Francois Daoust" href="https://www.w3.org/People/#fd">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="http://w3c.github.io/presentation-api/#dom-presentationrequest-start">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../common.js"></script>
<script>
add_completion_callback((tests, status) => {
// remove unserializable attributes, then send the result to the parent window
// note: a single test result is supposed to appear here.
parent.window.postMessage(JSON.parse(JSON.stringify({
type: 'presentation-api', test: tests[0], status: status
})), '*');
});
// disable timeout for manual tests
setup({explicit_timeout: true});
window.onmessage = function (ev) {
try {
// Presentation URLs are relative to the "controlling-ua" folder,
@ -57,6 +71,91 @@
parent.window.postMessage(err.name, '*');
});
}
else if (ev.data.match(/^reconnect\?id=(.*)$/)) {
promise_test(function (t) {
var presentationId = RegExp.$1;
var phase = -1, actual = -1, connection, waitConnection;
var description = [
"Phase #1: Promise is resolved",
"Phase #2: 'connectionavailable' event fired",
"Phase #3: 'connect' event fired"
].map(d => { return '(Reconnecting in a nested browsing context) ' + d; });
var count = function(evt) { actual++; return evt; };
var checkPhase = function(evt) {
phase++;
assert_equals(description[actual], description[phase], 'Event order is incorrect.');
return evt;
};
request = new PresentationRequest(urls);
var eventWatcher = new EventWatcher(t, request, 'connectionavailable');
var waitConnectionavailable = eventWatcher.wait_for('connectionavailable').then(count).then(function (evt) {
connection = connection || evt.connection; return evt;
});
return request.reconnect(presentationId).then(count).then(checkPhase).then(function (c) {
// Reconnecting Phase #1: Promise is resolved
connection = c;
assert_equals(connection.state, 'connecting', 'Check the initial state of the presentation connection.');
assert_equals(connection.id, presentationId, "The same presentation ID is set to the newly created presentation connection.");
assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.');
var eventWatcher = new EventWatcher(t, connection, 'connect');
waitConnect = eventWatcher.wait_for('connect').then(count);
// Reconnecting Phase #2: "connectionavailable" event is fired
return waitConnectionavailable;
}).then(checkPhase).then(function (evt) {
assert_true(evt instanceof PresentationConnectionAvailableEvent, 'An event using PresentationConnectionAvailableEvent is fired.');
assert_true(evt.isTrusted, 'The event is a trusted event.');
assert_false(evt.bubbles, 'The event does not bubbles.');
assert_false(evt.cancelable, 'The event is not cancelable.');
assert_equals(evt.type, 'connectionavailable', 'The event name is "connectionavailable".');
assert_equals(evt.target, request, 'event.target is the presentation request.');
assert_true(evt.connection instanceof PresentationConnection, 'event.connection is a presentation connection.');
assert_equals(evt.connection, connection, 'event.connection is set to the presentation which the promise is resolved with.');
// Reconnecting Phase #3: "connect" event is fired
return waitConnect;
}).then(checkPhase).then(function (evt) {
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".');
parent.window.postMessage({ type: 'presentation-api', test: { status: 0 } }, '*');
var terminateWatcher = new EventWatcher(t, connection, 'terminate');
// "terminate" event is fired
return terminateWatcher.wait_for('terminate');
}).then(function (evt) {
assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
assert_equals(evt.type, 'terminate', 'The event name is "terminate".');
assert_equals(evt.target, connection, 'event.target is the presentation connection.');
assert_equals(connection.state, 'terminated', 'The presentation connection state is set to "terminated".');
});
});
}
else if (ev.data.match(/^terminate\?id=(.*)$/)) {
var presentationId = RegExp.$1;
request = new PresentationRequest(urls);
request.reconnect(presentationId)
.then(function (c) {
parent.window.postMessage('reconnected', '*');
c.onterminate = function(evt) {
parent.window.postMessage({
isSimpleEvent: evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event,
type: evt.type,
checkConnection: evt.target === c,
state: c.state
}, '*');
};
})
.catch(function (err) {
parent.window.postMessage(err.name, '*');
});
}
else if (ev.data === 'getAvailability') {
request = new PresentationRequest(urls);
request.getAvailability()

View file

@ -35,49 +35,55 @@
const stash = new Stash(stashIds.toReceiver, stashIds.toController);
const addConnection = connection => {
connection.onconnect = function() {
let result = [], testCase;
let connection, count = 0;
this.onmessage = event => {
// PresentationConnection_send-manual.html
if (testCase === 'send') {
if (typeof event.data === 'string') {
result.push({ type: 'text', data: event.data });
}
// default value of connection.binaryType is "arraybuffer"
else if(event.data instanceof ArrayBuffer) {
result.push({ type: 'binary', data: toText(event.data) });
if (compare(event.data, message5)) {
stash.send(JSON.stringify(result));
}
}
else {
result.push({ type: 'error' });
const addConnection = c => {
let result = [], testCase;
connection = c;
count++;
connection.onmessage = event => {
// PresentationConnection_send-manual.https.html
if (testCase === 'send') {
if (typeof event.data === 'string') {
result.push({ type: 'text', data: event.data });
}
// default value of connection.binaryType is "arraybuffer"
else if(event.data instanceof ArrayBuffer) {
result.push({ type: 'binary', data: toText(event.data) });
if (compare(event.data, message5)) {
stash.send(JSON.stringify(result));
}
}
};
stash.receive().then(data => {
testCase = data;
// PresentationConnection_send-manual.html
if (testCase === 'send') {
stash.send('ok');
else {
result.push({ type: 'error' });
}
// PresentationConnection_onmessage-manual.html
else if (testCase === 'onmessage') {
connection.send(message1); // string
connection.send(message2); // string
connection.send(new Blob([message3])); // Blob
connection.send(message4.buffer); // ArrayBuffer
connection.send(message5); // ArrayBufferView
stash.receive().then(data => {
connection.send(message5);
});
}
});
}
};
stash.receive().then(data => {
testCase = data;
// PresentationConnection_send-manual.https.html
if (testCase === 'send') {
stash.send('ok');
}
// PresentationConnection_onmessage-manual.https.html
else if (testCase === 'onmessage') {
connection.send(message1); // string
connection.send(message2); // string
connection.send(new Blob([message3])); // Blob
connection.send(message4.buffer); // ArrayBuffer
connection.send(message5); // ArrayBufferView
stash.receive().then(data => {
connection.send(message5);
});
}
// PresentationConnection_onclose-manual.https.html
else if (testCase === 'close') {
connection.close();
}
});
};
navigator.presentation.receiver.connectionList
@ -89,4 +95,4 @@
addConnection(connection);
});
});
</script>
</script>