mirror of
https://github.com/servo/servo.git
synced 2025-06-16 20:34:30 +00:00
Update web-platform-tests to revision 74bae78af4b95a2f0ca3a81df9c7fe3143f24bbc
This commit is contained in:
parent
fb95f9df9c
commit
02c1eed999
150 changed files with 2395 additions and 829 deletions
|
@ -1,4 +1,5 @@
|
|||
[url-in-tags-revoke.window.html]
|
||||
expected: TIMEOUT
|
||||
[Fetching a blob URL immediately before revoking it works in an iframe.]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -14,3 +15,6 @@
|
|||
[Opening a blob URL in a new window by clicking an <a> tag works immediately before revoking the URL.]
|
||||
expected: FAIL
|
||||
|
||||
[Fetching a blob URL immediately before revoking it works in <script> tags.]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,2 @@
|
|||
[insert-inline-in-blocks-n-inlines-begin-001.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[insert-inline-in-blocks-n-inlines-begin-003.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[insert-inline-in-blocks-n-inlines-end-001.xht]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[insert-inline-in-blocks-n-inlines-end-003.xht]
|
||||
type: reftest
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[insert-inline-in-blocks-n-inlines-middle-001.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[insert-inline-in-blocks-n-inlines-middle-003.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[c5525-fltmult-000.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[border-padding-bleed-001.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[border-padding-bleed-002.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[border-padding-bleed-003.xht]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-028.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[background-size-030.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[flexbox_order-box.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[ttwf-reftest-flex-direction-row-reverse.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[ttwf-reftest-flex-order.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[font-variant-alternates-18.html]
|
||||
expected: FAIL
|
|
@ -257,3 +257,9 @@
|
|||
[font-weight(valid): Out-of-range simple calc value (should be clamped): calc(1001)]
|
||||
expected: FAIL
|
||||
|
||||
[font-style(valid): 'oblique' followed by calc with out of range value (should be clamped): oblique calc(-91deg)]
|
||||
expected: FAIL
|
||||
|
||||
[font-style(valid): 'oblique' followed by calc with out of range value (should be clamped): oblique calc(91deg)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
[font-style-parsing.html]
|
||||
[Font-style (computed): 'oblique' followed by calc is valid even if it must be clamped (with computation)]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by calc is valid even if it must be clamped (no computation)]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by minimum -90 degree angle is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'italic' is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by positive angle in turns is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by fractional angle is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by positive angle in degrees is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by positive angle in gradians is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by positive angle in radians is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by zero degrees is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by calc is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by calc is valid even if it mixes units (with computation)]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by positive angle is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by maxumum 90 degree angle is valid]
|
||||
expected: FAIL
|
||||
|
||||
[Font-style (computed): 'oblique' followed by negative angle is valid]
|
||||
expected: FAIL
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
|
||||
[single-byte-decoder.html?XMLHttpRequest]
|
||||
expected: TIMEOUT
|
||||
expected: CRASH
|
||||
[ISO-8859-2: iso_8859-2:1987 (XMLHttpRequest)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -312,15 +312,3 @@
|
|||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html */*;charset=gbk]
|
||||
expected: FAIL
|
||||
|
||||
[<iframe>: combined response Content-Type: text/html;" \\" text/plain]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -11,3 +11,6 @@
|
|||
[X-Content-Type-Options%3A%20nosniff%0C]
|
||||
expected: FAIL
|
||||
|
||||
[Content-Type-Options%3A%20nosniff]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[traverse_the_history_4.html]
|
||||
[traverse_the_history_5.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[link-error-fired-before-scripting-unblocked.html]
|
||||
[Check if the stylesheet's error event is fired before the pending parsing-blocking script is unblocked]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[link-load-fired-before-scripting-unblocked.html]
|
||||
[Check if the stylesheet's load event is fired before the pending parsing-blocking script is unblocked]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[stylesheet-not-removed-until-next-stylesheet-loads.html]
|
||||
[Check that a style sheet loaded by a <link> is available until its successor is loaded]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
[autoplay-hidden.optional.html]
|
||||
expected: TIMEOUT
|
||||
[Allow delaying autoplay until video elements become visible]
|
||||
expected: FAIL
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[non-active-document.html]
|
||||
[DOMParser]
|
||||
expected: FAIL
|
||||
|
||||
[createHTMLDocument]
|
||||
expected: FAIL
|
||||
|
||||
[<template>]
|
||||
expected: FAIL
|
||||
|
|
@ -12,3 +12,6 @@
|
|||
[Verifies the resolution of entry.startTime is at least 5 microseconds.]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Verifies the resolution of performance.now() is at least 5 microseconds.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[realtimeanalyser-fft-scaling.html]
|
||||
expected: TIMEOUT
|
||||
[X 2048-point FFT peak position is not equal to 64. Got 0.]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[import-in-moduleworker.html]
|
||||
expected: ERROR
|
||||
[Base URL in module dedicated workers: import]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[sharedworker-in-worker.html]
|
||||
expected: ERROR
|
||||
[Base URL in workers: new SharedWorker()]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[block_formatting_context_with_margin_a.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[inline_block_baseline_a.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[overconstrained_block.html]
|
||||
expected: FAIL
|
2
tests/wpt/mozilla/meta/css/stacked_layers.html.ini
Normal file
2
tests/wpt/mozilla/meta/css/stacked_layers.html.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
[stacked_layers.html]
|
||||
expected: FAIL
|
2
tests/wpt/mozilla/meta/css/transform_skew_a.html.ini
Normal file
2
tests/wpt/mozilla/meta/css/transform_skew_a.html.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
[transform_skew_a.html]
|
||||
expected: FAIL
|
|
@ -3,6 +3,7 @@
|
|||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
|
@ -47,7 +48,7 @@ async_test(t => {
|
|||
animation.play();
|
||||
|
||||
assert_equals(data, '0.4');
|
||||
waitTwoAnimationFrames(t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(1).then(t.step_func_done(() => {
|
||||
assert_equals(getComputedStyle(target).opacity, '0.5');
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -8,26 +8,25 @@ function registerPassthroughAnimator() {
|
|||
`);
|
||||
}
|
||||
|
||||
function registerConstantLocalTimeAnimator(localTime) {
|
||||
return runInAnimationWorklet(`
|
||||
registerAnimator('constant_time', class {
|
||||
animate(currentTime, effect) { effect.localTime = ${localTime}; }
|
||||
});
|
||||
`);
|
||||
}
|
||||
|
||||
|
||||
function runInAnimationWorklet(code) {
|
||||
return CSS.animationWorklet.addModule(
|
||||
URL.createObjectURL(new Blob([code], {type: 'text/javascript'}))
|
||||
);
|
||||
}
|
||||
|
||||
function waitForAnimationFrames(count, callback) {
|
||||
function rafCallback() {
|
||||
if (count <= 0) {
|
||||
callback();
|
||||
} else {
|
||||
count -= 1;
|
||||
window.requestAnimationFrame(rafCallback);
|
||||
}
|
||||
}
|
||||
rafCallback();
|
||||
};
|
||||
|
||||
// Wait for two main thread frames to guarantee that compositor has produced
|
||||
// at least one frame. Note that this is a Chrome-only concept.
|
||||
function waitTwoAnimationFrames(callback) {
|
||||
waitForAnimationFrames(2, callback);
|
||||
};
|
||||
function waitForAsyncAnimationFrames(count) {
|
||||
// In Chrome, waiting for N+1 main thread frames guarantees that compositor has produced
|
||||
// at least N frames.
|
||||
// TODO(majidvp): re-evaluate this choice once other browsers have implemented
|
||||
// AnimationWorklet.
|
||||
return waitForAnimationFrames(count + 1);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
background-color: #00ff00;
|
||||
}
|
||||
</style>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="../common.js"></script>
|
||||
|
||||
<script id="iframe_worklet" type="text/worklet">
|
||||
|
@ -32,7 +33,7 @@ runInAnimationWorklet(
|
|||
const effect = new KeyframeEffect(target, [{ opacity: 0 }], { duration: 1000 });
|
||||
const animation = new WorkletAnimation('iframe_animator', effect);
|
||||
animation.play();
|
||||
waitTwoAnimationFrames( _ => {
|
||||
waitForAnimationFrames(2).then(_ => {
|
||||
window.parent.postMessage(getComputedStyle(target).opacity, '*');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,15 +3,9 @@
|
|||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<script id="worklet_code" type="text/worklet">
|
||||
registerAnimator("test_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = currentTime;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Creates a DOM structure like:
|
||||
|
@ -63,15 +57,14 @@ function createAndPlayTestAnimation(elements, timeline_orientation) {
|
|||
timeRange: 1000,
|
||||
orientation: timeline_orientation
|
||||
});
|
||||
const animation = new WorkletAnimation('test_animator', effect, timeline);
|
||||
const animation = new WorkletAnimation('passthrough', effect, timeline);
|
||||
animation.play();
|
||||
}
|
||||
|
||||
setup(setupAndRegisterTests, {explicit_done: true});
|
||||
|
||||
function setupAndRegisterTests() {
|
||||
const worklet_code = document.getElementById('worklet_code').textContent;
|
||||
runInAnimationWorklet(worklet_code).then(() => {
|
||||
registerPassthroughAnimator().then(() => {
|
||||
// Note that block horizontal-tb is tested implicitly in the basic
|
||||
// ScrollTimeline tests (as it is the default).
|
||||
async_test(
|
||||
|
@ -104,7 +97,7 @@ function block_vertical_lr(t) {
|
|||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.25 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(2).then(t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
|
@ -120,7 +113,7 @@ function block_vertical_rl(t) {
|
|||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(2).then(t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
|
@ -136,7 +129,7 @@ function inline_horizontal_tb_rtl(t) {
|
|||
elements.scroller.scrollWidth - elements.scroller.clientWidth;
|
||||
elements.scroller.scrollLeft = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(2).then(t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
|
@ -151,7 +144,7 @@ function inline_vertical_writing_mode_ltr(t) {
|
|||
elements.scroller.scrollHeight - elements.scroller.clientHeight;
|
||||
elements.scroller.scrollTop = 0.25 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(2).then(t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
|
@ -167,7 +160,7 @@ function inline_vertical_writing_mode_rtl(t) {
|
|||
elements.scroller.scrollHeight - elements.scroller.clientHeight;
|
||||
elements.scroller.scrollTop = 0.75 * maxScroll;
|
||||
|
||||
waitForAnimationFrames(3, t.step_func_done(() => {
|
||||
waitForAsyncAnimationFrames(2).then(t.step_func_done(() => {
|
||||
assert_equals(
|
||||
getComputedStyle(elements.box).transform, 'matrix(1, 0, 0, 1, 0, 50)');
|
||||
}));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
|
@ -15,33 +16,21 @@
|
|||
|
||||
<script>
|
||||
function CreateTest(target, effect, verify, test_name) {
|
||||
async_test(t => {
|
||||
runInAnimationWorklet(
|
||||
document.getElementById('simple_animate').textContent
|
||||
).then(_ => {
|
||||
const animation = new WorkletAnimation('test_animator', effect);
|
||||
promise_test(async function() {
|
||||
await registerConstantLocalTimeAnimator(2000);
|
||||
const animation = new WorkletAnimation('constant_time', effect);
|
||||
animation.play();
|
||||
|
||||
waitTwoAnimationFrames(() => {
|
||||
await waitForAsyncAnimationFrames(1);
|
||||
// waitTwoAnimationFrames guarantees a compositor frame that could update
|
||||
// the opacity value in the worklet. Meanwhile, getComputedStyle needs an
|
||||
// extra frame to fetch the updated value.
|
||||
window.requestAnimationFrame(t.step_func_done(() => {
|
||||
await waitForNextFrame();
|
||||
verify();
|
||||
animation.cancel();
|
||||
}));
|
||||
});
|
||||
});
|
||||
}, test_name);
|
||||
}
|
||||
</script>
|
||||
<script id="simple_animate" type="text/worklet">
|
||||
registerAnimator("test_animator", class {
|
||||
animate(currentTime, effect) {
|
||||
effect.localTime = 2000;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="target1" class='target'></div>
|
||||
<div id="target2" class='target'></div>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="common.js"></script>
|
||||
|
||||
<style>
|
||||
|
@ -17,8 +18,8 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
test(function() {
|
||||
registerPassthroughAnimator();
|
||||
promise_test(async function() {
|
||||
await registerPassthroughAnimator();
|
||||
let playFunc = function() {
|
||||
let effect = new KeyframeEffect(
|
||||
document.getElementById('target'),
|
||||
|
|
|
@ -8,19 +8,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'HeartRate device properties';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
bluetooth_test(
|
||||
() => getHealthThermometerService()
|
||||
.then(({service}) => Promise.all([
|
||||
service.getCharacteristic('temperature_measurement'),
|
||||
service.getCharacteristic('measurement_interval')]))
|
||||
service.getCharacteristic('measurement_interval')
|
||||
]))
|
||||
.then(([temperature_measurement, measurement_interval]) => {
|
||||
let tm_expected_properties =
|
||||
new TestCharacteristicProperties(['indicate']);
|
||||
assert_properties_equal(temperature_measurement.properties,
|
||||
tm_expected_properties);
|
||||
assert_properties_equal(
|
||||
temperature_measurement.properties, tm_expected_properties);
|
||||
|
||||
let mi_expected_properties =
|
||||
new TestCharacteristicProperties(['read', 'write', 'indicate']);
|
||||
assert_properties_equal(measurement_interval.properties,
|
||||
mi_expected_properties);
|
||||
}), test_desc);
|
||||
let mi_expected_properties = new TestCharacteristicProperties(
|
||||
['read', 'write', 'indicate']);
|
||||
assert_properties_equal(
|
||||
measurement_interval.properties, mi_expected_properties);
|
||||
}),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,12 +8,14 @@
|
|||
'use strict';
|
||||
const test_desc = 'Same parent service returned from multiple characteristics.';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
bluetooth_test(
|
||||
() => getHealthThermometerService()
|
||||
.then(({service}) => Promise.all([
|
||||
service.getCharacteristic('measurement_interval'),
|
||||
service.getCharacteristic('temperature_measurement')
|
||||
]))
|
||||
.then(characteristics =>
|
||||
assert_equals(characteristics[0].service, characteristics[1].service)),
|
||||
.then(
|
||||
characteristics => assert_equals(
|
||||
characteristics[0].service, characteristics[1].service)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
const test_desc = '[SameObject] test for BluetoothRemoteGATTCharacteristic ' +
|
||||
'service.';
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(({characteristic}) =>
|
||||
bluetooth_test(
|
||||
() => getMeasurementIntervalCharacteristic().then(
|
||||
({characteristic}) =>
|
||||
assert_equals(characteristic.service, characteristic.service)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
const test_desc = 'Bluetooth IDL test';
|
||||
|
||||
test(() => {
|
||||
assert_throws(new TypeError(), () => new Bluetooth(),
|
||||
assert_throws(
|
||||
new TypeError(), () => new Bluetooth(),
|
||||
'the constructor should not be callable with "new"');
|
||||
assert_throws(new TypeError(), () => Bluetooth(),
|
||||
assert_throws(
|
||||
new TypeError(), () => Bluetooth(),
|
||||
'the constructor should not be callable');
|
||||
|
||||
// Bluetooth implements BluetoothDiscovery;
|
||||
|
|
|
@ -9,23 +9,28 @@
|
|||
const test_desc_idl = 'BluetoothDevice IDL test.';
|
||||
|
||||
test(() => {
|
||||
assert_throws(new TypeError(), () => new BluetoothDevice(),
|
||||
assert_throws(
|
||||
new TypeError(), () => new BluetoothDevice(),
|
||||
'the constructor should not be callable with "new"');
|
||||
assert_throws(new TypeError(), () => BluetoothDevice(),
|
||||
assert_throws(
|
||||
new TypeError(), () => BluetoothDevice(),
|
||||
'the constructor should not be callable');
|
||||
}, test_desc_idl);
|
||||
|
||||
const test_desc_attr = 'BluetoothDevice attributes.';
|
||||
let device;
|
||||
bluetooth_test(() => getConnectedHealthThermometerDevice()
|
||||
.then(({device}) => {
|
||||
bluetooth_test(
|
||||
() => getConnectedHealthThermometerDevice().then(({device}) => {
|
||||
assert_equals(device.constructor.name, 'BluetoothDevice');
|
||||
var old_device_id = device.id;
|
||||
assert_throws(new TypeError(), () => device.id = 'overwritten',
|
||||
assert_throws(
|
||||
new TypeError(), () => device.id = 'overwritten',
|
||||
'the device id should not be writable');
|
||||
assert_throws(new TypeError(), () => device.name = 'overwritten',
|
||||
assert_throws(
|
||||
new TypeError(), () => device.name = 'overwritten',
|
||||
'the device name should not be writable');
|
||||
assert_equals(device.id, old_device_id);
|
||||
assert_equals(device.name, 'Health Thermometer');
|
||||
}), test_desc_attr);
|
||||
}),
|
||||
test_desc_attr);
|
||||
</script>
|
||||
|
|
|
@ -19,7 +19,8 @@ test(() => {
|
|||
assert_equals(BluetoothUUID.getDescriptor(NaN), base_uuid);
|
||||
}, 'NaN returns basic uuid');
|
||||
|
||||
test(() => {
|
||||
test(
|
||||
() => {
|
||||
let max_uuid = 'ffffffff-0000-1000-8000-00805f9b34fb';
|
||||
let nine_digits = 0xfffffffff;
|
||||
let thirteen_digits = 0xfffffffffffff;
|
||||
|
@ -31,9 +32,11 @@ test(() => {
|
|||
assert_equals(BluetoothUUID.getCharacteristic(thirteen_digits), max_uuid);
|
||||
assert_equals(BluetoothUUID.getDescriptor(thirteen_digits), max_uuid);
|
||||
assert_equals(BluetoothUUID.getService(fourteen_digits), base_uuid);
|
||||
assert_equals(BluetoothUUID.getCharacteristic(fourteen_digits), base_uuid);
|
||||
assert_equals(
|
||||
BluetoothUUID.getCharacteristic(fourteen_digits), base_uuid);
|
||||
assert_equals(BluetoothUUID.getDescriptor(fourteen_digits), base_uuid);
|
||||
}, 'Values between 0xfffffffff (8 digits) and 0xffffffffffffff (14 digits)' +
|
||||
},
|
||||
'Values between 0xfffffffff (8 digits) and 0xffffffffffffff (14 digits)' +
|
||||
'should return max UUID');
|
||||
|
||||
test(() => {
|
||||
|
@ -54,7 +57,8 @@ test(() => {
|
|||
let adeadbeef_alias = 0xADEADBEEF;
|
||||
let adeadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
|
||||
assert_equals(BluetoothUUID.getService(adeadbeef_alias), adeadbeef_uuid);
|
||||
assert_equals(BluetoothUUID.getCharacteristic(adeadbeef_alias), adeadbeef_uuid);
|
||||
assert_equals(
|
||||
BluetoothUUID.getCharacteristic(adeadbeef_alias), adeadbeef_uuid);
|
||||
assert_equals(BluetoothUUID.getDescriptor(adeadbeef_alias), adeadbeef_uuid);
|
||||
}, 'Only first 32bits should be used.');
|
||||
|
||||
|
@ -68,30 +72,39 @@ test(() => {
|
|||
test(() => {
|
||||
let all_caps_uuid = '1A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D';
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getService(all_caps_uuid));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(all_caps_uuid));
|
||||
assert_throws(
|
||||
TypeError(), () => BluetoothUUID.getCharacteristic(all_caps_uuid));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(all_caps_uuid));
|
||||
}, 'A UUID String with uppercase letters is an invalid UUID.');
|
||||
|
||||
test(() => {
|
||||
let string_alias = 'deadbeef';
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getService(string_alias));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(string_alias));
|
||||
assert_throws(
|
||||
TypeError(), () => BluetoothUUID.getCharacteristic(string_alias));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(string_alias));
|
||||
}, 'A 32bit *String* alias is invalid.');
|
||||
|
||||
test(() => {
|
||||
let invalid_character_uuid = '0000000g-0000-1000-8000-00805f9b34fb';
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getService(invalid_character_uuid));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(invalid_character_uuid));
|
||||
assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(invalid_character_uuid));
|
||||
assert_throws(
|
||||
TypeError(), () => BluetoothUUID.getService(invalid_character_uuid));
|
||||
assert_throws(
|
||||
TypeError(),
|
||||
() => BluetoothUUID.getCharacteristic(invalid_character_uuid));
|
||||
assert_throws(
|
||||
TypeError(), () => BluetoothUUID.getDescriptor(invalid_character_uuid));
|
||||
}, 'A UUID with invalid characters is an invalid UUID.');
|
||||
|
||||
test(() => {
|
||||
assert_equals(BluetoothUUID.getService('alert_notification'),
|
||||
assert_equals(
|
||||
BluetoothUUID.getService('alert_notification'),
|
||||
'00001811-0000-1000-8000-00805f9b34fb');
|
||||
assert_equals(BluetoothUUID.getCharacteristic('aerobic_heart_rate_lower_limit'),
|
||||
assert_equals(
|
||||
BluetoothUUID.getCharacteristic('aerobic_heart_rate_lower_limit'),
|
||||
'00002a7e-0000-1000-8000-00805f9b34fb');
|
||||
assert_equals(BluetoothUUID.getDescriptor('gatt.characteristic_extended_properties'),
|
||||
assert_equals(
|
||||
BluetoothUUID.getDescriptor('gatt.characteristic_extended_properties'),
|
||||
'00002900-0000-1000-8000-00805f9b34fb');
|
||||
}, 'A valid UUID from a name.');
|
||||
|
||||
|
@ -136,7 +149,8 @@ test(() => {
|
|||
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(undefined));
|
||||
assert_equals(BluetoothUUID.canonicalUUID(null), base_uuid);
|
||||
assert_equals(BluetoothUUID.canonicalUUID(false), base_uuid);
|
||||
assert_equals(BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1));
|
||||
assert_equals(
|
||||
BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1));
|
||||
assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(NaN));
|
||||
|
||||
// getService
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
const test_desc = '[SameObject] test for navigator.bluetooth';
|
||||
|
||||
test(() => {
|
||||
assert_true('bluetooth' in navigator,
|
||||
'navigator.bluetooth exists.');
|
||||
assert_true('bluetooth' in navigator, 'navigator.bluetooth exists.');
|
||||
}, 'navigator.bluetooth IDL test');
|
||||
|
||||
test(() => {
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
const test_desc = 'Device with empty name and no UUIDs nearby. Should be ' +
|
||||
'found if acceptAllDevices is true.';
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: ''})
|
||||
bluetooth_test(
|
||||
() =>
|
||||
setUpPreconnectedDevice({name: ''})
|
||||
.then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
|
||||
.then(device => assert_equals(device.name, '')),
|
||||
test_desc);
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
const test_desc = 'A device with name and no UUIDs nearby. Should be found if ' +
|
||||
const test_desc =
|
||||
'A device with name and no UUIDs nearby. Should be found if ' +
|
||||
'acceptAllDevices is true.';
|
||||
const name = 'LE Device';
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: name})
|
||||
bluetooth_test(
|
||||
() =>
|
||||
setUpPreconnectedDevice({name: name})
|
||||
.then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
|
||||
.then(device => assert_equals(device.name, name)),
|
||||
test_desc);
|
||||
|
|
|
@ -14,9 +14,10 @@ const expected = new DOMException(
|
|||
'requestDevice() options. https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => getConnectedHealthThermometerDevice({acceptAllDevices: true})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryServices(),
|
||||
expected)),
|
||||
bluetooth_test(
|
||||
() => getConnectedHealthThermometerDevice({acceptAllDevices: true})
|
||||
.then(
|
||||
({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryServices(), expected)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
const test_desc = 'requestDevice called with acceptAllDevices: true and with ' +
|
||||
'optionalServices. Should get access to services.';
|
||||
|
||||
bluetooth_test(() => getTwoHealthThermometerServicesDevice()
|
||||
bluetooth_test(
|
||||
() => getTwoHealthThermometerServicesDevice()
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
acceptAllDevices: true,
|
||||
optionalServices: ['health_thermometer']
|
||||
|
@ -19,8 +20,10 @@ bluetooth_test(() => getTwoHealthThermometerServicesDevice()
|
|||
.then(services => {
|
||||
assert_equals(services.length, 2);
|
||||
services.forEach(service => {
|
||||
assert_equals(service.uuid,
|
||||
assert_equals(
|
||||
service.uuid,
|
||||
BluetoothUUID.getService('health_thermometer'));
|
||||
});
|
||||
}), test_desc);
|
||||
}),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -13,13 +13,13 @@ const expected = new DOMException(
|
|||
'https://goo.gl/4NeimX',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({
|
||||
knownServiceUUIDs: ['human_interface_device']
|
||||
})
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({
|
||||
filters: [{services: ['human_interface_device']}]
|
||||
}),
|
||||
bluetooth_test(
|
||||
() =>
|
||||
setUpPreconnectedDevice({knownServiceUUIDs: ['human_interface_device']})
|
||||
.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(
|
||||
{filters: [{services: ['human_interface_device']}]}),
|
||||
expected, 'Requesting blocklisted service rejects.')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,19 +8,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'Blocklisted UUID in optionalServices is removed and ' +
|
||||
'access not granted.';
|
||||
const expected = new DOMException('Origin is not allowed to access the ' +
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access the ' +
|
||||
'service. Tip: Add the service UUID to \'optionalServices\' in ' +
|
||||
'requestDevice() options. https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice({
|
||||
bluetooth_test(
|
||||
() => getDiscoveredHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['human_interface_device']
|
||||
})
|
||||
})
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
.then(
|
||||
() => fake_peripheral.setNextGATTConnectionResponse(
|
||||
{code: HCI_SUCCESS}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(() => Promise.all([
|
||||
assert_promise_rejects_with_message(
|
||||
|
@ -28,6 +31,7 @@ bluetooth_test(() => getDiscoveredHealthThermometerDevice({
|
|||
expected, 'Blocklisted service not accessible.'),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryServices('human_interface_device'),
|
||||
expected, 'Blocklisted services not accessible.')])),
|
||||
expected, 'Blocklisted services not accessible.')
|
||||
])),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -10,10 +10,11 @@ const test_desc = 'A device name between 29 and 248 bytes is valid.';
|
|||
const DEVICE_NAME = 'a_device_name_that_is_longer_than_29_bytes_but_' +
|
||||
'shorter_than_248_bytes';
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{name: DEVICE_NAME}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{name: DEVICE_NAME}]}))
|
||||
.then(device => assert_equals(device.name, DEVICE_NAME)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
const test_desc = 'A filter must restrict the devices in some way.';
|
||||
const expected = new TypeError();
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{}]}),
|
||||
expected),
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{}]}), expected),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'An empty |filters| member should result in a TypeError';
|
||||
const expected = new DOMException('Failed to execute \'requestDevice\' on ' +
|
||||
const expected = new DOMException(
|
||||
'Failed to execute \'requestDevice\' on ' +
|
||||
'\'Bluetooth\': \'filters\' member must be non-empty to find any devices.',
|
||||
new TypeError());
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: []}),
|
||||
expected),
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: []}), expected),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,36 +9,29 @@
|
|||
const test_desc = 'requestDevice with empty namePrefix. ' +
|
||||
'Should reject with TypeError.';
|
||||
const expected = new TypeError();
|
||||
const test_specs = [{
|
||||
filters: [{ namePrefix: ''}]
|
||||
}, {
|
||||
filters: [{ namePrefix: '', name: 'Name'}]
|
||||
}, {
|
||||
filters: [{ namePrefix: '', services: ['heart_rate']}]
|
||||
}, {
|
||||
filters: [{ namePrefix: '', name: 'Name', services: ['heart_rate']}]
|
||||
}, {
|
||||
filters: [{ namePrefix: ''}],
|
||||
const test_specs = [
|
||||
{filters: [{namePrefix: ''}]}, {filters: [{namePrefix: '', name: 'Name'}]},
|
||||
{filters: [{namePrefix: '', services: ['heart_rate']}]},
|
||||
{filters: [{namePrefix: '', name: 'Name', services: ['heart_rate']}]},
|
||||
{filters: [{namePrefix: ''}], optionalServices: ['heart_rate']},
|
||||
{filters: [{namePrefix: '', name: 'Name'}], optionalServices: ['heart_rate']},
|
||||
{
|
||||
filters: [{namePrefix: '', services: ['heart_rate']}],
|
||||
optionalServices: ['heart_rate']
|
||||
}, {
|
||||
filters: [{ namePrefix: '', name: 'Name'}],
|
||||
},
|
||||
{
|
||||
filters: [{namePrefix: '', name: 'Name', services: ['heart_rate']}],
|
||||
optionalServices: ['heart_rate']
|
||||
}, {
|
||||
filters: [{ namePrefix: '', services: ['heart_rate']}],
|
||||
optionalServices: ['heart_rate']
|
||||
}, {
|
||||
filters: [{ namePrefix: '', name: 'Name', services: ['heart_rate']}],
|
||||
optionalServices: ['heart_rate']
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
bluetooth_test(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
test_specs.forEach(args => {
|
||||
test_promises = test_promises
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args),
|
||||
expected));
|
||||
test_promises = test_promises.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args), expected));
|
||||
});
|
||||
return test_promises;
|
||||
}, test_desc);
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,13 +11,11 @@ const expected = new TypeError();
|
|||
|
||||
bluetooth_test(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
generateRequestDeviceArgsWithServices([]).forEach(args => {
|
||||
test_promises = test_promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args),
|
||||
expected,
|
||||
'Services member must contain at least one service'))
|
||||
});
|
||||
generateRequestDeviceArgsWithServices([]).forEach(
|
||||
args => {test_promises = test_promises.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args), expected,
|
||||
'Services member must contain at least one service'))});
|
||||
return test_promises;
|
||||
}, test_desc);
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,28 +6,24 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = "RequestDeviceOptions should have exactly one of " +
|
||||
"'filters' or 'acceptAllDevices:true'. Reject with TypeError if not.";
|
||||
const test_desc = 'RequestDeviceOptions should have exactly one of ' +
|
||||
'\'filters\' or \'acceptAllDevices:true\'. Reject with TypeError if not.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'requestDevice' on 'Bluetooth': " +
|
||||
"Either 'filters' should be present or " +
|
||||
"'acceptAllDevices' should be true, but not both.",
|
||||
'Failed to execute \'requestDevice\' on \'Bluetooth\': ' +
|
||||
'Either \'filters\' should be present or ' +
|
||||
'\'acceptAllDevices\' should be true, but not both.',
|
||||
new TypeError());
|
||||
const test_specs = [
|
||||
{},
|
||||
{optionalServices: ['heart_rate']},
|
||||
{filters: [], acceptAllDevices: true},
|
||||
{}, {optionalServices: ['heart_rate']}, {filters: [], acceptAllDevices: true},
|
||||
{filters: [], acceptAllDevices: true, optionalServices: ['heart_rate']}
|
||||
];
|
||||
|
||||
bluetooth_test(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
test_specs.forEach(args => {
|
||||
test_promises = test_promises
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args),
|
||||
expected))
|
||||
});
|
||||
test_specs.forEach(
|
||||
args => {test_promises = test_promises.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args), expected))});
|
||||
return test_promises;
|
||||
}, test_desc);
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
const test_desc = 'Unicode string with utf8 representation longer than 248 ' +
|
||||
'bytes in \'name\' must throw TypeError.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'requestDevice' on 'Bluetooth': " +
|
||||
"A device name can't be longer than 248 bytes.",
|
||||
'Failed to execute \'requestDevice\' on \'Bluetooth\': ' +
|
||||
'A device name can\'t be longer than 248 bytes.',
|
||||
new TypeError());
|
||||
// \u2764's UTF-8 respresentation is 3 bytes long.
|
||||
// 83 chars * 3 bytes/char = 249 bytes
|
||||
const unicode_name = '\u2764'.repeat(83);
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{name: unicode_name}]}),
|
||||
expected),
|
||||
test_desc);
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
'use strict';
|
||||
const test_desc = 'A device name longer than 248 must reject.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'requestDevice' on 'Bluetooth': A device " +
|
||||
"name can't be longer than 248 bytes.",
|
||||
'Failed to execute \'requestDevice\' on \'Bluetooth\': A device ' +
|
||||
'name can\'t be longer than 248 bytes.',
|
||||
new TypeError());
|
||||
const name_too_long = 'a'.repeat(249);
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{name: name_too_long}]}),
|
||||
expected,
|
||||
'Device name longer than 248'),
|
||||
expected, 'Device name longer than 248'),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
const test_desc = 'Unicode string with utf8 representation longer than 248 ' +
|
||||
'bytes in \'namePrefix\' must throw NotFoundError.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'requestDevice' on 'Bluetooth': " +
|
||||
"A device name can't be longer than 248 bytes.",
|
||||
'Failed to execute \'requestDevice\' on \'Bluetooth\': ' +
|
||||
'A device name can\'t be longer than 248 bytes.',
|
||||
new TypeError());
|
||||
// \u2764's UTF-8 respresentation is 3 bytes long.
|
||||
// 83 chars * 3 bytes/char = 249 bytes
|
||||
const unicode_name = '\u2764'.repeat(83);
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{namePrefix: unicode_name}]}),
|
||||
expected),
|
||||
test_desc);
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
'use strict';
|
||||
const test_desc = 'A device name prefix longer than 248 must reject.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'requestDevice' on 'Bluetooth': A device " +
|
||||
"name can't be longer than 248 bytes.",
|
||||
'Failed to execute \'requestDevice\' on \'Bluetooth\': A device ' +
|
||||
'name can\'t be longer than 248 bytes.',
|
||||
new TypeError());
|
||||
const name_too_long = 'a'.repeat(249);
|
||||
|
||||
bluetooth_test(() => assert_promise_rejects_with_message(
|
||||
bluetooth_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({filters: [{namePrefix: name_too_long}]}),
|
||||
expected,
|
||||
'Device name longer than 248'),
|
||||
expected, 'Device name longer than 248'),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,8 +11,11 @@ const test_desc = 'A unicode device name of 248 bytes is valid.';
|
|||
// 124 chars * 2 bytes/char = 248 bytes
|
||||
const DEVICE_NAME = '\u00A1'.repeat(124);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(() => requestDeviceWithTrustedClick({ filters: [{name: DEVICE_NAME}]}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{name: DEVICE_NAME}]}))
|
||||
.then(device => assert_equals(device.name, DEVICE_NAME)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,8 +9,11 @@
|
|||
const test_desc = 'A device name of 248 bytes is valid.';
|
||||
const DEVICE_NAME = 'a'.repeat(248);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(() => requestDeviceWithTrustedClick({ filters: [{name: DEVICE_NAME}]}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{name: DEVICE_NAME}]}))
|
||||
.then(device => assert_equals(device.name, DEVICE_NAME)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,10 +11,11 @@ const test_desc = 'A unicode device namePrefix of 248 bytes is valid.';
|
|||
// 124 chars * 2 bytes/char = 248 bytes
|
||||
const DEVICE_NAME = '\u00A1'.repeat(124);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{namePrefix: DEVICE_NAME}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{namePrefix: DEVICE_NAME}]}))
|
||||
.then(device => assert_equals(device.name, DEVICE_NAME)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,10 +9,11 @@
|
|||
const test_desc = 'A device namePrefix of 248 bytes is valid.';
|
||||
const DEVICE_NAME = 'a'.repeat(248);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{namePrefix: DEVICE_NAME}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: DEVICE_NAME})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{namePrefix: DEVICE_NAME}]}))
|
||||
.then(device => assert_equals(device.name, DEVICE_NAME)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
const test_desc = 'requestDevice() requires an argument.';
|
||||
const expected = new TypeError();
|
||||
|
||||
promise_test(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(),
|
||||
expected),
|
||||
promise_test(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(), expected),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -12,10 +12,11 @@ const test_desc = 'A name containing unicode characters whose utf8 length ' +
|
|||
// 9 chars * 3 bytes/char = 27 bytes
|
||||
const valid_unicode_name = '\u2764'.repeat(9);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: valid_unicode_name})
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{name: valid_unicode_name}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: valid_unicode_name})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{name: valid_unicode_name}]}))
|
||||
.then(device => assert_equals(device.name, valid_unicode_name)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -12,10 +12,11 @@ const test_desc = 'A namePrefix containing unicode characters whose utf8 ' +
|
|||
// 9 chars * 3 bytes/char = 27 bytes
|
||||
const valid_unicode_name = '\u2764'.repeat(9);
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: valid_unicode_name})
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{namePrefix: valid_unicode_name}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpPreconnectedDevice({name: valid_unicode_name})
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{namePrefix: valid_unicode_name}]}))
|
||||
.then(device => assert_equals(device.name, valid_unicode_name)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,37 +8,34 @@
|
|||
'use strict';
|
||||
const test_desc = 'Invalid optional service must reject the promise.';
|
||||
const expected = new TypeError();
|
||||
const test_specs = [{
|
||||
const test_specs = [
|
||||
{optionalServices: ['wrong_service'], filters: [{services: ['heart_rate']}]},
|
||||
{
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{services: ['heart_rate']}]
|
||||
}, {
|
||||
filters: [{services: ['heart_rate'], name: 'Name'}]
|
||||
},
|
||||
{
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ services: ['heart_rate'], name: 'Name'}]
|
||||
}, {
|
||||
filters: [{services: ['heart_rate'], namePrefix: 'Pre'}]
|
||||
},
|
||||
{
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ services: ['heart_rate'], namePrefix: 'Pre'}]
|
||||
}, {
|
||||
filters: [{services: ['heart_rate'], name: 'Name', namePrefix: 'Pre'}]
|
||||
},
|
||||
{optionalServices: ['wrong_service'], filters: [{name: 'Name'}]}, {
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ services: ['heart_rate'], name: 'Name', namePrefix: 'Pre'}]
|
||||
}, {
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ name: 'Name'}]
|
||||
}, {
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ name: 'Name', namePrefix: 'Pre'}]
|
||||
}, {
|
||||
optionalServices: ['wrong_service'],
|
||||
filters: [{ namePrefix: 'Pre'}]
|
||||
}];
|
||||
filters: [{name: 'Name', namePrefix: 'Pre'}]
|
||||
},
|
||||
{optionalServices: ['wrong_service'], filters: [{namePrefix: 'Pre'}]}
|
||||
];
|
||||
|
||||
bluetooth_test(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
test_specs.forEach(args => {
|
||||
test_promises =
|
||||
test_promises.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args),
|
||||
expected));
|
||||
test_promises = test_promises.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args), expected));
|
||||
});
|
||||
return test_promises;
|
||||
}, test_desc);
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -12,11 +12,10 @@ const expected = new TypeError();
|
|||
bluetooth_test(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
generateRequestDeviceArgsWithServices(['wrong_service']).forEach(args => {
|
||||
test_promises = test_promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args),
|
||||
expected));
|
||||
test_promises = test_promises.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(args), expected));
|
||||
});
|
||||
return test_promises;
|
||||
}, test_desc);
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -13,7 +13,8 @@ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
|
|||
'/bluetooth/resources/health-thermometer-iframe.html'
|
||||
let iframe = document.createElement('iframe');
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerDevice()
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerDevice()
|
||||
// 1. Load the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
iframe.src = cross_origin_src;
|
||||
|
@ -23,16 +24,18 @@ bluetooth_test(() => setUpHealthThermometerDevice()
|
|||
// 2. Request the device from the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestDevice'
|
||||
}, '*');
|
||||
iframe.contentWindow.postMessage(
|
||||
{type: 'RequestDevice'}, '*');
|
||||
});
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, 'SecurityError: requestDevice() ' +
|
||||
assert_equals(
|
||||
messageEvent.data,
|
||||
'SecurityError: requestDevice() ' +
|
||||
'called from cross-origin iframe.');
|
||||
resolve();
|
||||
}
|
||||
})), test_desc);
|
||||
})),
|
||||
test_desc);
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -8,21 +8,28 @@
|
|||
'use strict';
|
||||
const test_desc = 'Discover a device using alias, name, or UUID.';
|
||||
|
||||
bluetooth_test(() => getConnectedHealthThermometerDevice()
|
||||
// Chrome will always close the previous chooser in the process of handling
|
||||
// a user gesture for the next request, so these need to be done
|
||||
// sequentially.
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [health_thermometer.alias]}]
|
||||
}))
|
||||
.then(device => assert_equals(device.constructor.name, 'BluetoothDevice'))
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [health_thermometer.name]}]
|
||||
}))
|
||||
.then(device => assert_equals(device.constructor.name, 'BluetoothDevice'))
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [health_thermometer.uuid]}]
|
||||
}))
|
||||
.then(device => assert_equals(device.constructor.name, 'BluetoothDevice')),
|
||||
bluetooth_test(
|
||||
() => getConnectedHealthThermometerDevice()
|
||||
// Chrome will always close the previous chooser in the process of
|
||||
// handling a user gesture for the next request, so these need to
|
||||
// be done sequentially.
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [health_thermometer.alias]}]}))
|
||||
.then(
|
||||
device =>
|
||||
assert_equals(device.constructor.name, 'BluetoothDevice'))
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [health_thermometer.name]}]}))
|
||||
.then(
|
||||
device =>
|
||||
assert_equals(device.constructor.name, 'BluetoothDevice'))
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [health_thermometer.uuid]}]}))
|
||||
.then(
|
||||
device => assert_equals(
|
||||
device.constructor.name, 'BluetoothDevice')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,17 +8,21 @@
|
|||
'use strict';
|
||||
const test_desc = 'requestDevice calls do not consume user gestures.';
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(() => callWithTrustedClick(() => {
|
||||
let first = navigator.bluetooth.requestDevice({
|
||||
filters: [{services: ['heart_rate']}]});
|
||||
let second = navigator.bluetooth.requestDevice({
|
||||
filters: [{services: ['heart_rate']}]});
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerAndHeartRateDevices().then(
|
||||
() => callWithTrustedClick(() => {
|
||||
let first = navigator.bluetooth.requestDevice(
|
||||
{filters: [{services: ['heart_rate']}]});
|
||||
let second = navigator.bluetooth.requestDevice(
|
||||
{filters: [{services: ['heart_rate']}]});
|
||||
return Promise.all([
|
||||
first.then(device => assert_equals(
|
||||
device.constructor.name, 'BluetoothDevice')),
|
||||
second.then(device => assert_equals(
|
||||
device.constructor.name, 'BluetoothDevice')),
|
||||
first.then(
|
||||
device =>
|
||||
assert_equals(device.constructor.name, 'BluetoothDevice')),
|
||||
second.then(
|
||||
device =>
|
||||
assert_equals(device.constructor.name, 'BluetoothDevice')),
|
||||
]);
|
||||
})), test_desc);
|
||||
})),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,50 +11,47 @@ let matching_services = [health_thermometer.uuid];
|
|||
let matching_name = 'Health Thermometer';
|
||||
let matching_namePrefix = 'Health';
|
||||
|
||||
let test_specs = [{
|
||||
let test_specs = [
|
||||
{
|
||||
filters: [{
|
||||
services: matching_services,
|
||||
}]
|
||||
}, {
|
||||
},
|
||||
{
|
||||
filters: [{
|
||||
services: matching_services,
|
||||
name: matching_name,
|
||||
}]
|
||||
}, {
|
||||
filters: [{
|
||||
services: matching_services,
|
||||
namePrefix: matching_namePrefix
|
||||
}]
|
||||
}, {
|
||||
},
|
||||
{filters: [{services: matching_services, namePrefix: matching_namePrefix}]}, {
|
||||
filters: [{
|
||||
name: matching_name,
|
||||
}],
|
||||
optionalServices: matching_services
|
||||
}, {
|
||||
filters: [{
|
||||
name: matching_name,
|
||||
namePrefix: matching_namePrefix
|
||||
}],
|
||||
},
|
||||
{
|
||||
filters: [{name: matching_name, namePrefix: matching_namePrefix}],
|
||||
optionalServices: matching_services
|
||||
}, {
|
||||
filters: [{
|
||||
namePrefix: matching_namePrefix
|
||||
}],
|
||||
},
|
||||
{
|
||||
filters: [{namePrefix: matching_namePrefix}],
|
||||
optionalServices: matching_services
|
||||
}, {
|
||||
},
|
||||
{
|
||||
filters: [{
|
||||
services: matching_services,
|
||||
name: matching_name,
|
||||
namePrefix: matching_namePrefix
|
||||
}]
|
||||
}];
|
||||
}
|
||||
];
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerDevice()
|
||||
.then(() => {
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerDevice().then(() => {
|
||||
let test_promises = Promise.resolve();
|
||||
test_specs.forEach(args => {
|
||||
test_promises = test_promises
|
||||
.then(() => requestDeviceWithTrustedClick(args))
|
||||
test_promises =
|
||||
test_promises.then(() => requestDeviceWithTrustedClick(args))
|
||||
.then(device => {
|
||||
// We always have access to the services in matching_services
|
||||
// because we include them in a filter or in optionalServices.
|
||||
|
@ -63,5 +60,6 @@ bluetooth_test(() => setUpHealthThermometerDevice()
|
|||
});
|
||||
});
|
||||
return test_promises;
|
||||
}), test_desc);
|
||||
}),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Reject with NotFoundError if Bluetooth is not supported.';
|
||||
const expected = new DOMException('Bluetooth Low Energy not available.',
|
||||
'NotFoundError');
|
||||
const expected =
|
||||
new DOMException('Bluetooth Low Energy not available.', 'NotFoundError');
|
||||
|
||||
bluetooth_test(() => navigator.bluetooth.test.setLESupported(false)
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({acceptAllDevices: true}),
|
||||
expected, 'Bluetooth Low Energy is not supported.')),
|
||||
bluetooth_test(
|
||||
() => navigator.bluetooth.test.setLESupported(false).then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({acceptAllDevices: true}), expected,
|
||||
'Bluetooth Low Energy is not supported.')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
'use strict';
|
||||
const test_desc = 'An empty name device can be obtained by empty name filter.'
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: ''})
|
||||
bluetooth_test(
|
||||
() =>
|
||||
setUpPreconnectedDevice({name: ''})
|
||||
.then(() => requestDeviceWithTrustedClick({filters: [{name: ''}]}))
|
||||
.then(device => assert_equals(device.name, '')),
|
||||
test_desc);
|
||||
|
|
|
@ -11,9 +11,11 @@ const expected = new DOMException(
|
|||
'Must be handling a user gesture to show a permission request.',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
navigator.bluetooth.requestDevice({filters:[{services:['heart_rate']}]}),
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerAndHeartRateDevices().then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
navigator.bluetooth.requestDevice(
|
||||
{filters: [{services: ['heart_rate']}]}),
|
||||
expected, 'User gesture is required')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Reject with NotFoundError if there is no BT radio present.';
|
||||
const expected = new DOMException('Bluetooth adapter not available.',
|
||||
'NotFoundError');
|
||||
const expected =
|
||||
new DOMException('Bluetooth adapter not available.', 'NotFoundError');
|
||||
|
||||
bluetooth_test(() => navigator.bluetooth.test.simulateCentral({state: 'absent'})
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick({
|
||||
filters: [{services: ['generic_access']}]
|
||||
}),
|
||||
bluetooth_test(
|
||||
() => navigator.bluetooth.test.simulateCentral({state: 'absent'})
|
||||
.then(
|
||||
() => assert_promise_rejects_with_message(
|
||||
requestDeviceWithTrustedClick(
|
||||
{filters: [{services: ['generic_access']}]}),
|
||||
expected, 'Bluetooth adapter is not present.')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -12,22 +12,25 @@ for (let i = 0; i < 5; i++) {
|
|||
iframes.push(document.createElement('iframe'));
|
||||
}
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerAndHeartRateDevices()
|
||||
// 1. Load the iframes.
|
||||
.then(() => {
|
||||
let promises = [];
|
||||
for (let iframe of iframes) {
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
iframe.src =
|
||||
'/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
promises.push(new Promise(resolve =>
|
||||
iframe.addEventListener('load', resolve)));
|
||||
promises.push(new Promise(
|
||||
resolve => iframe.addEventListener('load', resolve)));
|
||||
}
|
||||
return Promise.all(promises);
|
||||
})
|
||||
// 2. Request the device from the iframes.
|
||||
.then(() => new Promise(async (resolve) => {
|
||||
let numMessages = 0;
|
||||
window.onmessage = messageEvent => {
|
||||
window.onmessage =
|
||||
messageEvent => {
|
||||
assert_equals(messageEvent.data, 'Success');
|
||||
if (++numMessages === iframes.length) {
|
||||
resolve();
|
||||
|
@ -35,9 +38,10 @@ bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
|||
}
|
||||
|
||||
for (let iframe of iframes) {
|
||||
await callWithTrustedClick(() => iframe.contentWindow.postMessage({
|
||||
type: 'RequestDevice'
|
||||
}, '*'));
|
||||
await callWithTrustedClick(
|
||||
() => iframe.contentWindow.postMessage(
|
||||
{type: 'RequestDevice'}, '*'));
|
||||
}
|
||||
})), test_desc);
|
||||
})),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -14,26 +14,28 @@ const expected = 'SecurityError: requestDevice() called from cross-origin ' +
|
|||
|
||||
let iframe = document.createElement('iframe');
|
||||
|
||||
bluetooth_test(() => getConnectedHealthThermometerDevice()
|
||||
bluetooth_test(
|
||||
() => getConnectedHealthThermometerDevice()
|
||||
// 1. Load the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
iframe.sandbox.add('allow-scripts');
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
iframe.src =
|
||||
'/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', resolve);
|
||||
}))
|
||||
// 2. Request the device from the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestDevice'
|
||||
}, '*');
|
||||
iframe.contentWindow.postMessage(
|
||||
{type: 'RequestDevice'}, '*');
|
||||
});
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, expected);
|
||||
resolve();
|
||||
}
|
||||
})), test_desc);
|
||||
})),
|
||||
test_desc);
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -10,21 +10,23 @@ const test_desc = 'Returned device should always be the same.';
|
|||
let devices = [];
|
||||
let push = device => devices.push(device);
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [heart_rate.alias]}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [heart_rate.alias]}]}))
|
||||
.then(push)
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [heart_rate.name]}]
|
||||
}))
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [heart_rate.name]}]}))
|
||||
.then(push)
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: [heart_rate.uuid]}]
|
||||
}))
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: [heart_rate.uuid]}]}))
|
||||
.then(push)
|
||||
.then(() => {
|
||||
assert_equals(devices[0], devices[1]);
|
||||
assert_equals(devices[1], devices[2]);
|
||||
}), test_desc);
|
||||
}),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,10 +8,11 @@
|
|||
'use strict';
|
||||
const test_desc = 'Simple filter selects matching device.';
|
||||
|
||||
bluetooth_test(() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
}))
|
||||
bluetooth_test(
|
||||
() => setUpHealthThermometerAndHeartRateDevices()
|
||||
.then(
|
||||
() => requestDeviceWithTrustedClick(
|
||||
{filters: [{services: ['health_thermometer']}]}))
|
||||
.then(device => assert_equals(device.name, 'Health Thermometer')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -3,24 +3,24 @@
|
|||
let device, gatt;
|
||||
|
||||
function requestDeviceWithOptionsAndConnect(options) {
|
||||
return navigator.bluetooth.requestDevice(options)
|
||||
.then(device => device.gatt.connect());
|
||||
return navigator.bluetooth.requestDevice(options).then(
|
||||
device => device.gatt.connect());
|
||||
}
|
||||
|
||||
window.addEventListener('message', (messageEvent) => {
|
||||
switch (messageEvent.data.type) {
|
||||
case 'RequestDevice':
|
||||
navigator.bluetooth.requestDevice({
|
||||
filters: [{services: ['generic_access']}]
|
||||
})
|
||||
navigator.bluetooth
|
||||
.requestDevice({filters: [{services: ['generic_access']}]})
|
||||
.then(device => {
|
||||
if (device.constructor.name === 'BluetoothDevice') {
|
||||
parent.postMessage('Success', '*');
|
||||
} else {
|
||||
parent.postMessage(
|
||||
`FAIL: requestDevice in iframe returned ${device.name}`, '*');
|
||||
}}).catch(err => parent.postMessage(`${err.name}: ${err.message}`,
|
||||
'*'));
|
||||
}
|
||||
})
|
||||
.catch(err => parent.postMessage(`${err.name}: ${err.message}`, '*'));
|
||||
break;
|
||||
case 'RequestAndConnect':
|
||||
requestDeviceWithOptionsAndConnect(messageEvent.data.options)
|
||||
|
@ -28,7 +28,8 @@ window.addEventListener('message', (messageEvent) => {
|
|||
gatt = _;
|
||||
device = gatt.device;
|
||||
parent.postMessage('Connected', '*');
|
||||
}).catch(err => {
|
||||
})
|
||||
.catch(err => {
|
||||
parent.postMessage(`FAIL: ${err}`, '*');
|
||||
});
|
||||
break;
|
||||
|
@ -50,8 +51,8 @@ window.addEventListener('message', (messageEvent) => {
|
|||
.catch(err => parent.postMessage(`FAIL: ${err}`, '*'));
|
||||
break;
|
||||
default:
|
||||
parent.postMessage(`FAIL: Bad message type: ${messageEvent.data.type}`,
|
||||
'*');
|
||||
parent.postMessage(
|
||||
`FAIL: Bad message type: ${messageEvent.data.type}`, '*');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
const test_desc = '[SameObject] test for BluetoothRemoteGATTServer\'s device.';
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
bluetooth_test(
|
||||
() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
.then(
|
||||
() => fake_peripheral.setNextGATTConnectionResponse(
|
||||
{code: HCI_SUCCESS}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gatt => assert_equals(gatt.device, gatt.device)),
|
||||
test_desc);
|
||||
|
|
|
@ -8,11 +8,14 @@
|
|||
'use strict';
|
||||
const test_desc = 'Same parent device returned from multiple services.';
|
||||
|
||||
bluetooth_test(() => getTwoHealthThermometerServicesDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(({device}) => device.gatt.getPrimaryServices('health_thermometer'))
|
||||
.then(([service1, service2]) =>
|
||||
bluetooth_test(
|
||||
() => getTwoHealthThermometerServicesDevice(
|
||||
{filters: [{services: ['health_thermometer']}]})
|
||||
.then(
|
||||
({device}) =>
|
||||
device.gatt.getPrimaryServices('health_thermometer'))
|
||||
.then(
|
||||
([service1, service2]) =>
|
||||
assert_equals(service1.device, service2.device)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
'use strict';
|
||||
const test_desc = '[SameObject] test for BluetoothRemoteGATTService device.';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(({device}) => device.gatt.getPrimaryService('health_thermometer'))
|
||||
bluetooth_test(
|
||||
() => getHealthThermometerDevice(
|
||||
{filters: [{services: ['health_thermometer']}]})
|
||||
.then(
|
||||
({device}) =>
|
||||
device.gatt.getPrimaryService('health_thermometer'))
|
||||
.then(service => assert_equals(service.device, service.device)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Background Test: Large images with one auto size are correctly sized</title>
|
||||
<link rel="author" title="schenney" href="mailto:schenney@chromium.org">
|
||||
<link rel="help" href="http://www.w3.org/TR/css3-background">
|
||||
<link rel="match" href="reference/background-image-large-with-auto-ref.html">
|
||||
<style>
|
||||
.wide-div {
|
||||
background-image: url(support/green-1000x10.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 10000px auto;
|
||||
width: 1000px;
|
||||
height: 100px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.high-div {
|
||||
background-image: url(support/green-10x1000.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: auto 10000px;
|
||||
width: 100px;
|
||||
height: 1000px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class='wide-div'></div>
|
||||
<div class='high-div'></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Background Test Reference</title>
|
||||
<link rel="author" title="schenney" href="mailto:schenney@chromium.org">
|
||||
<style>
|
||||
.wide-div {
|
||||
background-image: url(../support/green-1000x10.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 10000px 100px;
|
||||
width: 1000px;
|
||||
height: 100px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.high-div {
|
||||
background-image: url(../support/green-10x1000.png);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100px 10000px;
|
||||
width: 100px;
|
||||
height: 1000px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class='wide-div'></div>
|
||||
<div class='high-div'></div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
After Width: | Height: | Size: 128 B |
Binary file not shown.
After Width: | Height: | Size: 161 B |
|
@ -147,6 +147,8 @@
|
|||
{ value: "oblique 20deg", isValid: true, expectedValue: "oblique", description: "'oblique' followed by default 20deg angle" },
|
||||
{ value: "oblique 90deg", isValid: true, description: "'oblique' followed by maxumum 90 degree angle" },
|
||||
{ value: "oblique -90deg", isValid: true, description: "'oblique' followed by minimum -90 degree angle" },
|
||||
{ value: "oblique calc(91deg)", isValid: true, expectedValue: "oblique 90deg", description: "'oblique' followed by calc with out of range value (should be clamped)" },
|
||||
{ value: "oblique calc(-91deg)", isValid: true, expectedValue: "oblique -90deg", description: "'oblique' followed by calc with out of range value (should be clamped)" },
|
||||
{ value: "oblique 0rad", isValid: true, expectedValue: "oblique 0deg", description: "'oblique' followed by angle in radians" },
|
||||
{ value: "oblique 20", isValid: false, description: "'oblique' followed by unit-less number" },
|
||||
{ value: "oblique 20px", isValid: false, description: "'oblique' followed by non-angle" },
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="test"></div>
|
||||
<script>
|
||||
|
||||
var testFontStyle = [
|
||||
{ style: "italic", expectedResult: true, message: "'italic' is valid" },
|
||||
{ style: "italic 20deg", expectedResult: false, message: "'italic' followed by angle is invalid" },
|
||||
|
@ -17,33 +16,45 @@
|
|||
{ style: "oblique", expectedResult: true, message: "'oblique' is valid" },
|
||||
{ style: "oblique 0deg", expectedResult: true, message: "'oblique' followed by zero degrees is valid" },
|
||||
{ style: "oblique 20deg", expectedResult: true, message: "'oblique' followed by positive angle in degrees is valid" },
|
||||
{ style: "oblique 0.5rad", expectedResult: true, message: "'oblique' followed by positive angle in radians is valid" },
|
||||
{ style: "oblique 20grad", expectedResult: true, message: "'oblique' followed by positive angle in gradians is valid" },
|
||||
{ style: "oblique 0.1turn", expectedResult: true, message: "'oblique' followed by positive angle in turns is valid" },
|
||||
{ style: "oblique 0.5rad", expectedResult: true, message: "'oblique' followed by positive angle in radians is valid", expectedValue: "oblique 28.6479deg" },
|
||||
{ style: "oblique 20grad", expectedResult: true, message: "'oblique' followed by positive angle in gradians is valid", expectedValue: "oblique 18deg" },
|
||||
{ style: "oblique 0.1turn", expectedResult: true, message: "'oblique' followed by positive angle in turns is valid", expectedValue: "oblique 36deg" },
|
||||
{ style: "oblique 20px", expectedResult: false, message: "'oblique' followed by number with invalid unit type is in valid" },
|
||||
{ style: "oblique -20deg", expectedResult: true, message: "'oblique' followed by negative angle is valid" },
|
||||
{ style: "oblique 20.1deg", expectedResult: true, message: "'oblique' followed by fractional angle is valid" },
|
||||
{ style: "oblique 20.5deg", expectedResult: true, message: "'oblique' followed by fractional angle is valid" },
|
||||
{ style: "oblique 90deg", expectedResult: true, message: "'oblique' followed by maxumum 90 degree angle is valid" },
|
||||
{ style: "oblique -90deg", expectedResult: true, message: "'oblique' followed by minimum -90 degree angle is valid" },
|
||||
{ style: "oblique 90.01deg", expectedResult: false, message: "'oblique' followed by positive out of range angle is in invalid" },
|
||||
{ style: "oblique -90.01deg", expectedResult: false, message: "'oblique' followed by negative out of range angle is in invalid" },
|
||||
{ style: "oblique 10", expectedResult: false, message: "'oblique' followed by unit-less value is invalid" },
|
||||
{ style: "oblique 20deg ", expectedResult: true, message: "'oblique' followed by positive angle is valid" },
|
||||
{ style: "oblique 30deg", expectedResult: true, message: "'oblique' followed by positive angle is valid" },
|
||||
{ style: "oblique a", expectedResult: false, message: "'oblique' followed by non-number is invalid" },
|
||||
{ style: "oblique 20deg a", expectedResult: false, message: "'oblique' and angle followed by non-number is invalid" },
|
||||
{ style: "oblique -", expectedResult: false, message: "'oblique' followed by isolated minus is invalid" },
|
||||
{ style: "oblique - 20deg", expectedResult: false, message: "'oblique' followed by minus and angle separated by space is invalid" },
|
||||
{ style: "oblique -a", expectedResult: false, message: "'oblique' followed by minus and non-number is invalid" },
|
||||
{ style: "oblique calc(50deg)", expectedResult: true, message: "'oblique' followed by calc is valid" },
|
||||
{ style: "oblique calc(-120deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it must be clamped (no computation)" },
|
||||
{ style: "oblique calc(6 * 20deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it must be clamped (with computation)" },
|
||||
{ style: "oblique calc(0.1rad + 1deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it mixes units (with computation)" }
|
||||
{ style: "oblique calc(50deg)", expectedResult: true, message: "'oblique' followed by calc is valid", expectedValue: "oblique 50deg" },
|
||||
{ style: "oblique calc(-120deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it must be clamped (no computation)", expectedValue: "oblique -90deg" },
|
||||
{ style: "oblique calc(6 * 20deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it must be clamped (with computation)", expectedValue: "oblique 90deg" },
|
||||
{ style: "oblique calc(10grad + 5deg)", expectedResult: true, message: "'oblique' followed by calc is valid even if it mixes units (with computation)", expectedValue: "oblique 14deg" }
|
||||
];
|
||||
|
||||
testFontStyle.forEach(function (testCase) {
|
||||
test(() => { assert_equals(window.CSS.supports("font-style", testCase.style), testCase.expectedResult, "Font-style: " + testCase.message); }, "Font-style: " + testCase.message);
|
||||
test(() => {
|
||||
assert_equals(window.CSS.supports("font-style", testCase.style), testCase.expectedResult, "Font-style supports: " + testCase.message);
|
||||
}, "Font-style (supports): " + testCase.message);
|
||||
});
|
||||
|
||||
testFontStyle.forEach(function (testCase) {
|
||||
if (testCase.expectedResult) {
|
||||
test(() => {
|
||||
let element = document.getElementById("test");
|
||||
element.style = "font-style: " + testCase.style;
|
||||
let expectedValue = (testCase.expectedValue) ? testCase.expectedValue : testCase.style;
|
||||
assert_equals(window.getComputedStyle(element).fontStyle, expectedValue, "Font-style computed style: " + testCase.message);
|
||||
}, "Font-style (computed): " + testCase.message);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test Reference: Test column-span:all when the body tag is the multi-column container</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
|
||||
<style>
|
||||
body {
|
||||
column-count: 1;
|
||||
column-rule: 6px solid;
|
||||
width: 400px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
/* column-count: 1 makes this behave like a real spanner. */
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div>block1</div>
|
||||
<div>
|
||||
<h3>spanner</h3>
|
||||
</div>
|
||||
<div>block2</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Multi-column Layout Test: Test column-span:all when the body tag is the multi-column container</title>
|
||||
<link rel="author" title="Ting-Yu Lin" href="tlin@mozilla.com">
|
||||
<link rel="author" title="Mozilla" href="http://www.mozilla.org/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#column-span">
|
||||
<link rel="match" href="multicol-span-all-007-ref.html">
|
||||
<meta name="assert" content="This test checks a column-span:all element is working if the body tag is the multi-column container.">
|
||||
|
||||
<style>
|
||||
body {
|
||||
column-count: 3;
|
||||
column-rule: 6px solid;
|
||||
width: 400px;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
h3 {
|
||||
column-span: all;
|
||||
outline: 1px solid blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div>block1</div>
|
||||
<div>
|
||||
<h3>spanner</h3> <!-- Put spanner in a subtree deliberately -->
|
||||
</div>
|
||||
<div>block2</div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue