Update web-platform-tests to revision 74bae78af4b95a2f0ca3a81df9c7fe3143f24bbc

This commit is contained in:
WPT Sync Bot 2019-01-17 20:37:38 -05:00
parent fb95f9df9c
commit 02c1eed999
150 changed files with 2395 additions and 829 deletions

View file

@ -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

View file

@ -0,0 +1,2 @@
[insert-inline-in-blocks-n-inlines-begin-001.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[insert-inline-in-blocks-n-inlines-begin-003.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[insert-inline-in-blocks-n-inlines-end-001.xht]
expected: FAIL

View file

@ -1,3 +0,0 @@
[insert-inline-in-blocks-n-inlines-end-003.xht]
type: reftest
expected: FAIL

View file

@ -0,0 +1,2 @@
[insert-inline-in-blocks-n-inlines-middle-001.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[insert-inline-in-blocks-n-inlines-middle-003.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[c5525-fltmult-000.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[border-padding-bleed-001.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[border-padding-bleed-002.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[border-padding-bleed-003.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[background-size-028.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[background-size-030.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[flexbox_order-box.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[ttwf-reftest-flex-direction-row-reverse.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[ttwf-reftest-flex-order.html]
expected: FAIL

View file

@ -1,2 +0,0 @@
[font-variant-alternates-18.html]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -32,7 +32,7 @@
[single-byte-decoder.html?XMLHttpRequest]
expected: TIMEOUT
expected: CRASH
[ISO-8859-2: iso_8859-2:1987 (XMLHttpRequest)]
expected: FAIL

View file

@ -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

View file

@ -11,3 +11,6 @@
[X-Content-Type-Options%3A%20nosniff%0C]
expected: FAIL
[Content-Type-Options%3A%20nosniff]
expected: FAIL

View file

@ -1,4 +1,4 @@
[traverse_the_history_4.html]
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,5 @@
[autoplay-hidden.optional.html]
expected: TIMEOUT
[Allow delaying autoplay until video elements become visible]
expected: FAIL
expected: TIMEOUT

View file

@ -0,0 +1,10 @@
[non-active-document.html]
[DOMParser]
expected: FAIL
[createHTMLDocument]
expected: FAIL
[<template>]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,4 @@
[import-in-moduleworker.html]
expected: ERROR
[Base URL in module dedicated workers: import]
expected: FAIL

View file

@ -1,5 +1,4 @@
[sharedworker-in-worker.html]
expected: ERROR
[Base URL in workers: new SharedWorker()]
expected: FAIL

View file

@ -0,0 +1,2 @@
[block_formatting_context_with_margin_a.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[inline_block_baseline_a.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[overconstrained_block.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[stacked_layers.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[transform_skew_a.html]
expected: FAIL

View file

@ -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');
}));
});

View file

@ -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);
}

View file

@ -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, '*');
});
});

View file

@ -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)');
}));

View file

@ -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>

View file

@ -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'),

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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;

View file

@ -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>

View file

@ -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

View file

@ -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(() => {

View file

@ -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);

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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);

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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" },

View file

@ -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>

View file

@ -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>

View file

@ -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