Update web-platform-tests to revision 58eb04cecbbec2e18531ab440225e38944a9c444

This commit is contained in:
Josh Matthews 2017-04-17 12:06:02 +10:00 committed by Anthony Ramine
parent 25e8bf69e6
commit 665817d2a6
35333 changed files with 1818077 additions and 16036 deletions

View file

@ -0,0 +1,138 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Receiving a message through PresentationConnection</title>
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="http://w3c.github.io/presentation-api/#receiving-a-message-through-presentationconnection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<script src="support/stash.js"></script>
<p id="notice">
Click the button below and select the available presentation display, to start the manual test. The test passes if a "PASS" result appears.<br>
<button id="presentBtn">Start Presentation Test</button>
</p>
<script>
setup({explicit_timeout: true});
const presentBtn = document.getElementById('presentBtn');
const message1 = '1st';
const message2 = '2nd';
const message3 = new Uint8Array([51, 114, 100]); // "3rd"
const message4 = new Uint8Array([52, 116, 104]); // "4th"
const message5 = new Uint8Array([108, 97, 115, 116]); // "last"
const toUint8Array = buf => {
return buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;
}
// compare two ArrayBuffer or Uint8Array
const compare = (a, b) => {
const p = toUint8Array(a);
const q = toUint8Array(b);
return !!p && !!q && p.every((item, index) => { return item === q[index]; });
};
presentBtn.onclick = () => {
presentBtn.disabled = true;
const stash = new Stash(stashIds.toController, stashIds.toReceiver);
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');
};
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();
});
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();
});
});
};
</script>

View file

@ -0,0 +1,128 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Sending a message through PresentationConnection</title>
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="http://w3c.github.io/presentation-api/#sending-a-message-through-presentationconnection">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="common.js"></script>
<script src="support/stash.js"></script>
<p id="notice">
Click the button below and select the available presentation display, to start the manual test. The test passes if a "PASS" result appears.<br>
<button id="presentBtn">Start Presentation Test</button>
</p>
<script>
setup({explicit_timeout: true});
const presentBtn = document.getElementById('presentBtn');
const message1 = '1st';
const message2 = '2nd';
const message3 = new Uint8Array([51, 114, 100]); // "3rd"
const message4 = new Uint8Array([52, 116, 104]); // "4th"
const message5 = new Uint8Array([108, 97, 115, 116]); // "last"
const toUint8Array = buf => {
return buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;
}
// convert ArrayBuffer or Uint8Array into string
const toText = buf => {
const arr = toUint8Array(buf);
return !buf ? null : arr.reduce((result, item) => {
return result + String.fromCharCode(item);
}, '');
}
presentBtn.onclick = () => {
presentBtn.disabled = true;
const stash = new Stash(stashIds.toController, stashIds.toReceiver);
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"');
});
});
};
</script>

View file

@ -13,4 +13,13 @@
'support/presentation.html',
castUrl
];
// Both a controlling side and a receiving one must share the same Stash ID to
// transmit data from one to the other. On the other hand, due to polling mechanism
// which cleans up a stash, stashes in both controller-to-receiver direction
// and one for receiver-to-controller are necessary.
window.stashIds = {
toController: '9bf08fea-a71a-42f9-b3c4-fa19499e4d12',
toReceiver: 'f1fdfd10-b606-4748-a644-0a8e9df3bdd6'
}
})(window);

View file

@ -23,10 +23,12 @@ dictionary EventInit {
<script id='idl' type="text/plain">
partial interface Navigator {
[SameObject]
readonly attribute Presentation? presentation;
[SecureContext,
SameObject]
readonly attribute Presentation presentation;
};
[SecureContext]
interface Presentation {
};
@ -34,22 +36,25 @@ partial interface Presentation {
attribute PresentationRequest? defaultRequest;
};
[Constructor(DOMString url),
Constructor(sequence<DOMString> urls)]
[SecureContext,
Constructor(USVString url),
Constructor(sequence<USVString> urls)]
interface PresentationRequest : EventTarget {
Promise<PresentationConnection> start();
Promise<PresentationConnection> reconnect(DOMString presentationId);
Promise<PresentationConnection> reconnect(USVString presentationId);
Promise<PresentationAvailability> getAvailability();
attribute EventHandler onconnectionavailable;
};
[SecureContext]
interface PresentationAvailability : EventTarget {
readonly attribute boolean value;
attribute EventHandler onchange;
};
[Constructor(DOMString type, PresentationConnectionAvailableEventInit eventInitDict)]
[SecureContext,
Constructor(DOMString type, PresentationConnectionAvailableEventInit eventInitDict)]
interface PresentationConnectionAvailableEvent : Event {
[SameObject]
readonly attribute PresentationConnection connection;
@ -71,40 +76,42 @@ enum BinaryType {
"arraybuffer"
};
[SecureContext]
interface PresentationConnection : EventTarget {
readonly attribute DOMString id;
readonly attribute DOMString url;
readonly attribute USVString id;
readonly attribute USVString url;
readonly attribute PresentationConnectionState state;
void close();
void terminate();
attribute EventHandler onconnect;
attribute EventHandler onclose;
attribute EventHandler onterminate;
attribute EventHandler onconnect;
attribute EventHandler onclose;
attribute EventHandler onterminate;
// Communication
attribute BinaryType binaryType;
attribute EventHandler onmessage;
attribute BinaryType binaryType;
attribute EventHandler onmessage;
void send(DOMString message);
void send(Blob data);
void send(ArrayBuffer data);
void send(ArrayBufferView data);
};
enum PresentationConnectionClosedReason {
enum PresentationConnectionCloseReason {
"error",
"closed",
"wentaway"
};
[Constructor(DOMString type, PresentationConnectionCloseEventInit eventInitDict)]
[SecureContext,
Constructor(DOMString type, PresentationConnectionCloseEventInit eventInitDict)]
interface PresentationConnectionCloseEvent : Event {
readonly attribute PresentationConnectionClosedReason reason;
readonly attribute DOMString message;
readonly attribute PresentationConnectionCloseReason reason;
readonly attribute DOMString message;
};
dictionary PresentationConnectionCloseEventInit : EventInit {
required PresentationConnectionClosedReason reason;
DOMString message = "";
required PresentationConnectionCloseReason reason;
DOMString message = "";
};
</script>
@ -117,7 +124,7 @@ dictionary PresentationConnectionCloseEventInit : EventInit {
idl_array.add_idls(idls);
window.presentation_request = new PresentationRequest("/presentation-api/receiving-ua/idlharness.html");
window.presentation_request_urls = new PresentationRequest(["/presentation-api/receiving-ua/idlharness.html",
"http://www.example.com/presentation.html"]);
"https://www.example.com/presentation.html"]);
navigator.presentation.defaultRequest = presentation_request;
idl_array.add_objects({
Presentation: ['navigator.presentation'],
@ -125,5 +132,4 @@ dictionary PresentationConnectionCloseEventInit : EventInit {
});
idl_array.test();
})();
</script>
</script>

View file

@ -3,22 +3,89 @@
<meta charset="utf-8">
<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="http://w3c.github.io/presentation-api/#interface-presentationconnectionlist">
<script src="../common.js"></script>
<script src="stash.js"></script>
<script>
var addConnection = function(connection) {
connection.onconnected = function () {
this.onmessage = function (evt) {
this.send(evt.data);
const message1 = '1st';
const message2 = '2nd';
const message3 = new Uint8Array([51, 114, 100]); // "3rd"
const message4 = new Uint8Array([52, 116, 104]); // "4th"
const message5 = new Uint8Array([108, 97, 115, 116]); // "last"
const toUint8Array = buf => {
return buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;
}
// convert ArrayBuffer or Uint8Array into string
const toText = buf => {
const arr = toUint8Array(buf);
return !buf ? null : arr.reduce((result, item) => {
return result + String.fromCharCode(item);
}, '');
}
// compare two ArrayBuffer or Uint8Array
const compare = (a, b) => {
const p = toUint8Array(a);
const q = toUint8Array(b);
return !!p && !!q && p.every((item, index) => { return item === q[index]; });
};
const stash = new Stash(stashIds.toReceiver, stashIds.toController);
const addConnection = connection => {
connection.onconnect = function() {
let result = [], testCase;
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' });
}
}
};
stash.receive().then(data => {
testCase = data;
// PresentationConnection_send-manual.html
if (testCase === 'send') {
stash.send('ok');
}
// 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);
});
}
});
};
};
navigator.presentation.receiver.connectionList
.then(function(list) {
list.onconnectionavailable = function(evt) {
.then(list => {
list.onconnectionavailable = evt => {
addConnection(evt.connection);
};
list.connections.map(function(connection) {
list.connections.map(connection => {
addConnection(connection);
});
});

View file

@ -0,0 +1,83 @@
var Stash = function(inbound, outbound) {
this.stashPath = '/presentation-api/controlling-ua/support/stash.py?id=';
this.inbound = inbound;
this.outbound = outbound;
}
// initialize a stash on wptserve
Stash.prototype.init = function() {
return Promise.all([
fetch(this.stashPath + this.inbound).then(response => {
return response.text();
}),
fetch(this.stashPath + this.outbound).then(response => {
return response.text();
})
]);
}
// upload a test result to a stash on wptserve
Stash.prototype.send = function(result) {
return fetch(this.stashPath + this.outbound, {
method: 'POST',
body: JSON.stringify({ type: 'data', data: result })
}).then(response => {
return response.text();
}).then(text => {
return text === 'ok' ? null : Promise.reject();
})
};
// wait until a test result is uploaded to a stash on wptserve
Stash.prototype.receive = function() {
return new Promise((resolve, reject) => {
let intervalId;
const interval = 500; // msec
const polling = () => {
return fetch(this.stashPath + this.inbound).then(response => {
return response.text();
}).then(text => {
if (text) {
try {
const json = JSON.parse(text);
if (json.type === 'data')
resolve(json.data);
else
reject();
} catch(e) {
resolve(text);
}
clearInterval(intervalId);
}
});
};
intervalId = setInterval(polling, interval);
});
};
// reset a stash on wptserve
Stash.prototype.stop = function() {
return Promise.all([
fetch(this.stashPath + this.inbound).then(response => {
return response.text();
}),
fetch(this.stashPath + this.outbound).then(response => {
return response.text();
})
]).then(() => {
return Promise.all([
fetch(this.stashPath + this.inbound, {
method: 'POST',
body: JSON.stringify({ type: 'stop' })
}).then(response => {
return response.text();
}),
fetch(this.stashPath + this.outbound, {
method: 'POST',
body: JSON.stringify({ type: 'stop' })
}).then(response => {
return response.text();
})
]);
});
}

View file

@ -0,0 +1,10 @@
def main(request, response):
key = request.GET.first("id")
if request.method == "POST":
request.server.stash.put(key, request.body)
return "ok"
else:
value = request.server.stash.take(key)
assert request.server.stash.take(key) is None
return value