mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Update web-platform-tests to revision 7bfbc0fa30aad867faa1c6cc748884be76635a08
This commit is contained in:
parent
0fa3248723
commit
65b0e306b7
87 changed files with 2402 additions and 622 deletions
File diff suppressed because it is too large
Load diff
|
@ -273,3 +273,9 @@
|
|||
[SubtleCrypto interface: calling unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, [object Object\]) on crypto.subtle with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[CryptoKey interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[SubtleCrypto interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -164,3 +164,9 @@
|
|||
[SubtleCrypto interface: calling unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, [object Object\]) on crypto.subtle with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[CryptoKey interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[SubtleCrypto interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[text-indent-on-blank-line-rtl-left-align.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
|||
[vh_not_refreshing_on_chrome.html]
|
||||
expected: FAIL
|
|
@ -504,3 +504,6 @@
|
|||
[CaretPosition interface: document.caretPositionFromPoint(5, 5) must inherit property "getClientRect()" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[CaretPosition interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -645,3 +645,9 @@
|
|||
[CSSStyleDeclaration interface: getComputedStyle(svg_element) must inherit property "parentRule" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[CSSPageRule interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[CSSMarginRule interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -774,3 +774,93 @@
|
|||
[DOMTokenList interface: document.body.classList must inherit property "supports(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[AbortController interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[AbortSignal interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[MutationObserver interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[MutationRecord interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for prepend([object Object\],[object Object\]) on Document]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for append([object Object\],[object Object\]) on Document]
|
||||
expected: FAIL
|
||||
|
||||
[DocumentType interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for before([object Object\],[object Object\]) on DocumentType]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for after([object Object\],[object Object\]) on DocumentType]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for replaceWith([object Object\],[object Object\]) on DocumentType]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for remove() on DocumentType]
|
||||
expected: FAIL
|
||||
|
||||
[DocumentFragment interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for prepend([object Object\],[object Object\]) on DocumentFragment]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for append([object Object\],[object Object\]) on DocumentFragment]
|
||||
expected: FAIL
|
||||
|
||||
[ShadowRoot interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for slot property on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for prepend([object Object\],[object Object\]) on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for append([object Object\],[object Object\]) on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for before([object Object\],[object Object\]) on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for after([object Object\],[object Object\]) on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for replaceWith([object Object\],[object Object\]) on Element]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for remove() on Element]
|
||||
expected: FAIL
|
||||
|
||||
[CharacterData interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for before([object Object\],[object Object\]) on CharacterData]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for after([object Object\],[object Object\]) on CharacterData]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for replaceWith([object Object\],[object Object\]) on CharacterData]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for remove() on CharacterData]
|
||||
expected: FAIL
|
||||
|
||||
[CDATASection interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -36,3 +36,6 @@
|
|||
[Element interface: document.createElementNS(null, "test") must inherit property "onfullscreenerror" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Unscopable handled correctly for fullscreen property on Document]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -13905,3 +13905,99 @@
|
|||
[OffscreenCanvas interface: operation getContext(OffscreenRenderingContextId, any)]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLAllCollection interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[DOMStringList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLMenuElement interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[AudioTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[AudioTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[VideoTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[VideoTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TextTrackList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TextTrack interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TextTrackCueList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TextTrackCue interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TimeRanges interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TrackEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLSlotElement interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[TextMetrics interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[Path2D interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[ImageBitmapRenderingContext interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[OffscreenCanvas interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[OffscreenCanvasRenderingContext2D interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[DataTransfer interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[DataTransferItemList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[DataTransferItem interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[DragEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[BarProp interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[ApplicationCache interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[PromiseRejectionEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[ImageBitmap interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[MessageChannel interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[MessagePort interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[BroadcastChannel interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[SharedWorker interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[HTMLMarqueeElement interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -54,3 +54,6 @@
|
|||
[DOMStringList interface: location.ancestorOrigins must inherit property "contains(DOMString)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[DOMStringList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -24,3 +24,6 @@
|
|||
[DOMStringList interface: operation contains(DOMString)]
|
||||
expected: FAIL
|
||||
|
||||
[DOMStringList interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -345,3 +345,9 @@
|
|||
[Performance interface: window.performance must inherit property "navigation" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceNavigationTiming interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceNavigation interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -48,3 +48,6 @@
|
|||
[PerformanceNavigationTiming interface: operation toJSON()]
|
||||
expected: FAIL
|
||||
|
||||
[PerformanceNavigationTiming interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[po-navigation.html]
|
||||
type: testharness
|
||||
[navigation entry is observable]
|
||||
expected: FAIL
|
||||
|
|
@ -186,3 +186,9 @@
|
|||
[UIEvent interface: new CompositionEvent("event") must inherit property "which" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[WheelEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[CompositionEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
[name-property.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[Test the name property of shared and dedicated workers via the name constructor option]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -597,3 +597,12 @@
|
|||
[BluetoothRemoteGATTDescriptor interface: bluetooth_descriptor must inherit property "writeValue(BufferSource)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[ValueEvent interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[BluetoothManufacturerDataMap interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
[BluetoothServiceDataMap interface: existence and properties of interface prototype object's @@unscopables property]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
// TODO(https://crbug.com/672127) Use this test case to test the rest of
|
||||
// characteristic functions.
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptor(user_description.name),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
// TODO(https://crbug.com/672127) Use this test case to test the rest of
|
||||
// characteristic functions.
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptors(user_description.uuid),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
// TODO(https://crbug.com/672127) Use this test case to test the rest of
|
||||
// characteristic functions.
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptors(user_description.name),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.startNotifications(),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.readValue(),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.writeValue(new ArrayBuffer(1 /* length */)),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let descriptor, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getUserDescriptionDescriptor()
|
||||
.then(_ => ({descriptor, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
descriptor.readValue(),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let descriptor, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getUserDescriptionDescriptor()
|
||||
.then(_ => ({descriptor, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
descriptor.writeValue(new ArrayBuffer(1 /* length */)),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,20 @@
|
|||
// TODO(https://crbug.com/672127) Use this test case to test the rest of
|
||||
// characteristic functions.
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.CALLS([
|
||||
getDescriptor(user_description.name)|
|
||||
getDescriptors(user_description.uuid)[UUID]|
|
||||
getDescriptors(user_description.name)]),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
const test_desc = 'Service gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let descriptor, fake_peripheral, fake_service;
|
||||
|
||||
bluetooth_test(() => getUserDescriptionDescriptor()
|
||||
.then(_ => ({descriptor, fake_peripheral, fake_service} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
descriptor.CALLS([
|
||||
readValue()|
|
||||
writeValue(new ArrayBuffer(1 /* length */))
|
||||
]),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
const test_desc = 'Service is removed before FUNCTION_NAME call. ' +
|
||||
'Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let service, fake_service, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
.then(_ => ({service, fake_service, fake_peripheral} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
service.CALLS([
|
||||
getCharacteristic('measurement_interval')|
|
||||
getCharacteristics()|
|
||||
getCharacteristics('measurement_interval')[UUID]
|
||||
]),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
|
@ -0,0 +1,26 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed before getCharacteristic call. ' +
|
||||
'Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let service, fake_service, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
.then(_ => ({service, fake_service, fake_peripheral} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
service.getCharacteristic('measurement_interval'),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,26 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed before getCharacteristics call. ' +
|
||||
'Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let service, fake_service, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
.then(_ => ({service, fake_service, fake_peripheral} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
service.getCharacteristics('measurement_interval'),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,26 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Service is removed before getCharacteristics call. ' +
|
||||
'Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Service no longer exists.',
|
||||
'InvalidStateError');
|
||||
let service, fake_service, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
.then(_ => ({service, fake_service, fake_peripheral} = _))
|
||||
.then(() => fake_service.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
service.getCharacteristics(),
|
||||
expected,
|
||||
'Service got removed.')),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
|
||||
<p>There should be a hotpink square in the bottom left corner of a larger blue square.</p>
|
||||
<div style="width:200px; background:blue;">
|
||||
<div style="height:100px;"></div>
|
||||
<div style="width:100px; height:100px; background:hotpink;"></div>
|
||||
</div>
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Text-indent on blank line in RTL container with text-align:left</title>
|
||||
<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
|
||||
<link rel="help" href="https://www.w3.org/TR/CSS22/text.html#propdef-text-indent" title="16.1 Indentation: the 'text-indent' property">
|
||||
<link rel="match" href="text-indent-on-blank-line-rtl-left-align-ref.html">
|
||||
<p>There should be a hotpink square in the bottom left corner of a larger blue square.</p>
|
||||
<div style="text-align:left; direction:rtl; text-indent:300px; line-height:100px; width:200px; background:blue;">
|
||||
<br>
|
||||
<div style="vertical-align:bottom; display:inline-block; width:100px; height:100px; background:hotpink;"></div>
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
.result {
|
||||
background: green;
|
||||
border-radius: 2px;
|
||||
margin: 10px;
|
||||
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="result"></div>
|
|
@ -0,0 +1,70 @@
|
|||
<!DOCTYPE html>
|
||||
<html class=reftest-wait>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#layout-invalidation">
|
||||
<link rel="match" href="style-map-multi-ref.html">
|
||||
<meta name="assert" content="This test checks that properties are correctly given to the layout function." />
|
||||
|
||||
<style>
|
||||
.test {
|
||||
background: red;
|
||||
margin: 10px;
|
||||
width: 100px;
|
||||
|
||||
/* Properties under test. */
|
||||
--foo: bar;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@supports (display: layout(test)) {
|
||||
.test {
|
||||
background: green;
|
||||
display: layout(test);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
|
||||
<div class="test"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerLayout('test', class {
|
||||
static get inputProperties() {
|
||||
return [ '--bar', '--foo', 'align-items', 'border-top-left-radius'];
|
||||
}
|
||||
|
||||
*intrinsicSizes() {}
|
||||
*layout(children, edges, constraints, styleMap) {
|
||||
const expected = [
|
||||
{property: '--bar', value: '[CSSUnparsedValue=]'},
|
||||
{property: '--foo', value: '[CSSUnparsedValue= bar]'},
|
||||
{property: 'align-items', value: '[CSSKeywordValue=normal]'},
|
||||
{property: 'border-top-left-radius', value: '[CSSUnitValue=2px]'},
|
||||
];
|
||||
|
||||
const actual = Array.from(styleMap.keys()).sort().map((property) => {
|
||||
const valueObject = styleMap.get(property);
|
||||
const value = '[' + valueObject.constructor.name + '=' + valueObject.toString() + ']';
|
||||
return {property, value};
|
||||
});
|
||||
|
||||
if (expected.length != actual.length)
|
||||
return {autoBlockSize: 0};
|
||||
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
if (expected[i].property != actual[i].property)
|
||||
return {autoBlockSize: 0};
|
||||
|
||||
if (expected[i].value != actual[i].value)
|
||||
return {autoBlockSize: 0};
|
||||
}
|
||||
|
||||
return {autoBlockSize: 100};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
.result {
|
||||
background: green;
|
||||
border-radius: 2px;
|
||||
margin: 10px;
|
||||
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="result"></div>
|
||||
<div class="result"></div>
|
||||
<div class="result"></div>
|
||||
<div class="result"></div>
|
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<html class=reftest-wait>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#layout-invalidation">
|
||||
<link rel="match" href="style-map-ref.html">
|
||||
<meta name="assert" content="This test checks that properties are correctly given to the layout function." />
|
||||
|
||||
<style>
|
||||
.test {
|
||||
background: red;
|
||||
margin: 10px;
|
||||
width: 100px;
|
||||
|
||||
/* Properties under test. */
|
||||
--foo: bar;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@supports (display: layout(test)) {
|
||||
.test {
|
||||
background: green;
|
||||
}
|
||||
|
||||
.test-0 { display: layout(test-0); }
|
||||
.test-1 { display: layout(test-1); }
|
||||
.test-2 { display: layout(test-2); }
|
||||
.test-3 { display: layout(test-3); }
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
|
||||
<div class="test test-0"></div>
|
||||
<div class="test test-1"></div>
|
||||
<div class="test test-2"></div>
|
||||
<div class="test test-3"></div>
|
||||
|
||||
<script>
|
||||
const tmpl = (test, idx) => {
|
||||
return `
|
||||
registerLayout('test-${idx}', class {
|
||||
static get inputProperties() { return ['${test.property}']; }
|
||||
|
||||
*intrinsicSizes() {}
|
||||
*layout(children, edges, constraints, styleMap) {
|
||||
const value = styleMap.get('${test.property}');
|
||||
const result = '[' + value.constructor.name + '=' + value.toString() + ']';
|
||||
if (result != '${test.expected}')
|
||||
return {autoBlockSize: 0};
|
||||
|
||||
const size = Array.from(styleMap.keys()).length;
|
||||
if (size != 1)
|
||||
return {autoBlockSize: 0};
|
||||
|
||||
return {autoBlockSize: 100};
|
||||
}
|
||||
});
|
||||
`;
|
||||
}
|
||||
|
||||
const tests = [
|
||||
{property: '--bar', expected: '[CSSUnparsedValue=]'},
|
||||
{property: '--foo', expected: '[CSSUnparsedValue= bar]'},
|
||||
{property: 'align-items', expected: '[CSSKeywordValue=normal]'},
|
||||
{property: 'border-top-left-radius', expected: '[CSSUnitValue=2px]'},
|
||||
];
|
||||
|
||||
const workletSource = tests.map(tmpl).join('\n');
|
||||
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, workletSource);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,42 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for position:sticky elements should not affect the flow position of other elements</title>
|
||||
|
||||
<style>
|
||||
.scroller {
|
||||
height: 200px;
|
||||
width: 100px;
|
||||
overflow-y: scroll;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.box {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.before {
|
||||
background-color: fuchsia;
|
||||
}
|
||||
|
||||
.after {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.padding {
|
||||
height: 450px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="scroller">
|
||||
<div class="before box"></div>
|
||||
<div class="box"></div>
|
||||
<div class="after box"></div>
|
||||
<div class="sticky box"></div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
|
||||
<div>You should see a fuchsia box, a one-box gap, an orange box, and then a green box above.</div>
|
|
@ -1,58 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<title>position:sticky elements should not affect the flow position of other elements</title>
|
||||
<link rel="match" href="position-sticky-inflow-position-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="This test checks that position:sticky elements do not affect the flow position of other elements" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<style>
|
||||
.scroller {
|
||||
position: relative;
|
||||
height: 200px;
|
||||
width: 100px;
|
||||
overflow: scroll;
|
||||
overflow-y: scroll;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#sticky {
|
||||
.sticky {
|
||||
background-color: green;
|
||||
position: sticky;
|
||||
top: 150px;
|
||||
}
|
||||
|
||||
#before {
|
||||
background-color: fuchsia;
|
||||
}
|
||||
|
||||
#after {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.box {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.before {
|
||||
background-color: fuchsia;
|
||||
}
|
||||
|
||||
.after {
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.padding {
|
||||
height: 500px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="scroller">
|
||||
<div id="before" class="box"></div>
|
||||
<div id="sticky" class="box"></div>
|
||||
<div id="after" class="box"></div>
|
||||
<div class="before box"></div>
|
||||
<div class="sticky box"></div>
|
||||
<div class="after box"></div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
// The sticky element is pushed to be stuck 150 pixels from the top.
|
||||
assert_equals(sticky.offsetTop, 150);
|
||||
|
||||
// Neither 'before' or 'after' should be affected by the change in the sticky
|
||||
// element's location.
|
||||
assert_equals(before.offsetTop, 0);
|
||||
assert_equals(after.offsetTop, before.clientHeight + sticky.clientHeight);
|
||||
}, 'sticky offset should not affect the position of other elements.');
|
||||
</script>
|
||||
<div>You should see a fuchsia box, a one-box gap, an orange box, and then a green box above.</div>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for position:sticky elements should properly interact with margins</title>
|
||||
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 180px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
width: 150px;
|
||||
height: 300px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
position: relative;
|
||||
background-color: green;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.padding {
|
||||
height: 385px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 0;
|
||||
document.getElementById('scroller2').scrollTop = 60;
|
||||
document.getElementById('scroller3').scrollTop = 120;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="indicator box" style="top: 0;"></div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="indicator box" style="top: 50px;"></div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="indicator box" style="top: 85px;"></div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
|
@ -1,49 +1,92 @@
|
|||
<!DOCTYPE html>
|
||||
<title>position:sticky elements should properly interact with margins</title>
|
||||
<link rel="match" href="position-sticky-margins-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="position:sticky elements should ignore margins when sticking, but consider them when making sure sticky elements do not escape their containing block" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 180px;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
<script src="resources/sticky-util.js"></script>
|
||||
.scroller {
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 300px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
<body></body>
|
||||
.holder {
|
||||
width: 130px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
position: sticky;
|
||||
background-color: green;
|
||||
top: 5px;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
left: 15px;
|
||||
position: absolute;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.padding {
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.margin = '15px';
|
||||
elements.scroller.scrollTop = 100;
|
||||
assert_equals(elements.sticky.offsetTop,
|
||||
elements.container.offsetTop + elements.filler.clientHeight + 15);
|
||||
}, 'Before sticking, the margin should be obeyed.');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.margin = '15px';
|
||||
|
||||
elements.scroller.scrollTop = 200;
|
||||
|
||||
// This math cancels to sticky.offsetTop == (scroller.scrollTop + 50), but
|
||||
// for clarity the calculations are left explicit.
|
||||
const nonStickyTopY = elements.container.offsetTop +
|
||||
elements.filler.clientHeight;
|
||||
const targetTopY = elements.scroller.scrollTop + 50;
|
||||
const stickyOffset = targetTopY - nonStickyTopY;
|
||||
|
||||
assert_equals(elements.sticky.offsetTop, nonStickyTopY + stickyOffset);
|
||||
}, 'Whilst stuck, the margin is irrelevant.');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.margin = '15px';
|
||||
|
||||
elements.scroller.scrollTop = 300;
|
||||
|
||||
const maxOffsetInContainer = elements.container.offsetTop +
|
||||
elements.container.clientHeight - elements.sticky.clientHeight;
|
||||
assert_equals(elements.sticky.offsetTop, maxOffsetInContainer - 15);
|
||||
}, 'The margin is taken into account when making sure the sticky element ' +
|
||||
'does not escape its container');
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 0;
|
||||
document.getElementById('scroller2').scrollTop = 60;
|
||||
document.getElementById('scroller3').scrollTop = 120;
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Before sticking, the margin should be obeyed. -->
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="indicator box" style="top: 15px;"></div>
|
||||
<div class="holder">
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Whilst stuck, the margin is irrelevant. -->
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="indicator box" style="top: 65px;"></div>
|
||||
<div class="holder">
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The margin does count when making sure the sticky element does not escape
|
||||
its containing block. -->
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="indicator box" style="top: 100px;"></div>
|
||||
<div class="holder">
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
<div class="padding"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for position:sticky elements should respect padding on their ancestor overflow element</title>
|
||||
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: green;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 175;
|
||||
document.getElementById('scroller3').scrollTop = 220;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 170px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 195px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 220px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
|
@ -1,54 +1,106 @@
|
|||
<!DOCTYPE html>
|
||||
<title>position:sticky elements should respect padding on their ancestor overflow element</title>
|
||||
<link rel="match" href="position-sticky-overflow-padding-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="This test checks that position:sticky elements respect padding on their ancestor overflow element" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
<script src="resources/sticky-util.js"></script>
|
||||
.scroller {
|
||||
/* The target sticky position should be offset by this padding. */
|
||||
padding: 20px 0;
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
<body></body>
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.prepadding {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.innerpadding {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: red;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
background-color: green;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.scroller.style.padding = '20px 0';
|
||||
|
||||
// Before sticking; the element isn't within the padding range.
|
||||
elements.scroller.scrollTop = 150;
|
||||
const nonStickyTopY = elements.container.offsetTop +
|
||||
elements.filler.clientHeight;
|
||||
assert_equals(elements.sticky.offsetTop, nonStickyTopY);
|
||||
}, 'A sticky element should not be affected by ancestor padding until it ' +
|
||||
'reaches it');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.top = '0';
|
||||
elements.scroller.style.padding = '20px 0';
|
||||
|
||||
elements.scroller.scrollTop = 200;
|
||||
|
||||
// This math cancels to sticky.offsetTop == (scroller.scrollTop + 50), but
|
||||
// for clarity the calculations are left explicit.
|
||||
const nonStickyTopY = elements.container.offsetTop +
|
||||
elements.filler.clientHeight;
|
||||
const targetTopY = elements.scroller.scrollTop;
|
||||
const stickyOffset = targetTopY - nonStickyTopY;
|
||||
|
||||
assert_equals(elements.sticky.offsetTop, nonStickyTopY + stickyOffset + 20);
|
||||
}, 'A sticky element should be offset by ancestor padding even when stuck');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.top = '0';
|
||||
elements.scroller.style.padding = '20px 0';
|
||||
|
||||
elements.scroller.scrollTop = 315;
|
||||
const maxOffsetInContainer = elements.container.offsetTop +
|
||||
elements.container.clientHeight - elements.sticky.clientHeight;
|
||||
assert_equals(elements.sticky.offsetTop, maxOffsetInContainer);
|
||||
}, 'Ancestor overflow padding does not allow a sticky element to escape its ' +
|
||||
'container');
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 175;
|
||||
document.getElementById('scroller3').scrollTop = 220;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="indicator box" style="top: 170px;"></div>
|
||||
<div class="contents">
|
||||
<div class="prepadding"></div>
|
||||
<div class="container">
|
||||
<div class="innerpadding"></div>
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="indicator box" style="top: 195px;"></div>
|
||||
<div class="contents">
|
||||
<div class="prepadding"></div>
|
||||
<div class="container">
|
||||
<div class="innerpadding"></div>
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="indicator box" style="top: 220px;"></div>
|
||||
<div class="contents">
|
||||
<div class="prepadding"></div>
|
||||
<div class="container">
|
||||
<div class="innerpadding"></div>
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for position:sticky should operate correctly for the root scroller</title>
|
||||
|
||||
<style>
|
||||
body {
|
||||
/* Assumption: 3000px is taller than any user agents test window size. */
|
||||
height: 3000px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: green;
|
||||
position: absolute;
|
||||
top: 750px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
window.scrollTo(0, 700);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="indicator box"></div>
|
||||
|
||||
<div style="position: absolute; top: 1000px;">You should see a green box above. No red should be visible.</div>
|
|
@ -1,31 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<title>position:sticky should operate correctly for the root scroller</title>
|
||||
<link rel="match" href="position-sticky-root-scroller-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="This test checks that position:sticky elements work when using the root (document) scroller" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
/* Assumption: 3000px is taller than any user agents test window size. */
|
||||
height: 3000px;
|
||||
}
|
||||
|
||||
#sticky {
|
||||
.indicator {
|
||||
background-color: red;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
background-color: green;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="sticky"></div>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
window.addEventListener('load', function() {
|
||||
window.scrollTo(0, 700);
|
||||
assert_equals(sticky.offsetTop, 700 + 50);
|
||||
}, 'Sticky elements work with the root (document) scroller');
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="indicator box" style="top: 750px;"></div>
|
||||
<div class="sticky box"></div>
|
||||
|
||||
<div style="position: absolute; top: 1000px;">You should see a green box above. No red should be visible.</div>
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for transforms on position:sticky elements should apply after sticking</title>
|
||||
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.rotated {
|
||||
transform: rotateX(60deg);
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.perspective {
|
||||
transform: perspective(3px) translateZ(1px);
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 50;
|
||||
document.getElementById('scroller3').scrollTop = 50;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="height: 100px; top: 75px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="rotated indicator" style="top: 100px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<!-- Required for blending. -->
|
||||
<div class="perspective" style="position: absolute; background: red; top: 100px;"></div>
|
||||
<div class="contents">
|
||||
<div class="perspective indicator" style="top: 100px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
|
@ -0,0 +1,67 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for translations on position:sticky elements should apply after sticking</title>
|
||||
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: green;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 70;
|
||||
document.getElementById('scroller3').scrollTop = 50;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 50px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 50px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="contents">
|
||||
<div class="indicator box" style="top: 200px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
|
@ -1,45 +1,92 @@
|
|||
<!DOCTYPE html>
|
||||
<title>translations on position:sticky elements should apply after sticking</title>
|
||||
<link rel="match" href="position-sticky-transforms-translate-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="This test checks that translations on position:sticky elements are carried out on their stuck position" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
<script src="resources/sticky-util.js"></script>
|
||||
.scroller {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
<body style="margin: 0;"></body>
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: red;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
background-color: green;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.transform = 'translateY(-100%)';
|
||||
elements.scroller.scrollTop = 100;
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
assert_equals(elements.sticky.getBoundingClientRect().y,
|
||||
elements.scroller.getBoundingClientRect().y);
|
||||
}, 'Translation transform can move sticky element past sticking point');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.transform = 'translateY(50%)';
|
||||
elements.scroller.scrollTop = 200;
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
const stickyElementOffset = elements.sticky.getBoundingClientRect().y -
|
||||
elements.scroller.getBoundingClientRect().y;
|
||||
assert_equals(stickyElementOffset, 100);
|
||||
}, 'Stuck elements can still be moved via translations');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.container.style.transform = 'translateY(100px)';
|
||||
elements.scroller.scrollTop = 200;
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
// Here the sticky element will originally have stuck at 50px from the top,
|
||||
// but is then 'pulled' downwards by the 100px container transform.
|
||||
const stickyElementOffset = elements.sticky.getBoundingClientRect().y -
|
||||
elements.scroller.getBoundingClientRect().y;
|
||||
assert_equals(stickyElementOffset, 150);
|
||||
}, 'The sticky element should stick before the container is offset by a ' +
|
||||
'translation');
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 70;
|
||||
document.getElementById('scroller3').scrollTop = 50;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="indicator box" style="top: 50px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container">
|
||||
<div class="sticky box" style="transform: translateY(-100%);"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The pre-transform sticky is not allowed to escape its containing block. -->
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="indicator box" style="top: 50px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container">
|
||||
<div class="sticky box" style="transform: translateY(-100%);"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The sticky element should stick before the container is transformed. -->
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="indicator box" style="top: 200px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container" style="transform: translateY(100px);">
|
||||
<div class="sticky box"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
||||
|
|
|
@ -1,49 +1,101 @@
|
|||
<!DOCTYPE html>
|
||||
<title>transforms on position:sticky elements should apply after sticking</title>
|
||||
<link rel="match" href="position-sticky-transforms-ref.html" />
|
||||
<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
|
||||
<meta name="assert" content="This test checks that transforms on position:sticky elements are carried out on their stuck position" />
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
.group {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
<script src="resources/sticky-util.js"></script>
|
||||
.scroller {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 200px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
<body style="margin: 0;"></body>
|
||||
.contents {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: red;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.sticky {
|
||||
background-color: green;
|
||||
position: sticky;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.rotated {
|
||||
transform: rotateX(60deg);
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.perspective {
|
||||
transform: perspective(3px) translateZ(1px);
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.transform = 'scale(2)';
|
||||
elements.scroller.scrollTop = 200;
|
||||
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
// Scaling the sticky element by 2 means its top-y moves (1/2 * height)
|
||||
// upwards, in this case placing it at the top of the viewport.
|
||||
const boundingRect = elements.sticky.getBoundingClientRect();
|
||||
assert_equals(boundingRect.y, elements.scroller.getBoundingClientRect().y);
|
||||
}, 'Scale transforms are carried out on the stuck element position');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.transform = 'rotateX(60deg)';
|
||||
elements.scroller.scrollTop = 200;
|
||||
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
// Rotating around the x-axis essentially 'squashes' it (from the camera's
|
||||
// viewpoint), in this case shifting the offset to 75 rather than 50.
|
||||
const stickyElementOffset = elements.sticky.getBoundingClientRect().y -
|
||||
elements.scroller.getBoundingClientRect().y;
|
||||
assert_equals(stickyElementOffset, 75);
|
||||
}, 'Rotate transforms are carried out on the stuck element position');
|
||||
|
||||
test(() => {
|
||||
const elements = setupStickyTest('top', 50);
|
||||
elements.sticky.style.transform = 'perspective(3px) translateZ(1px)';
|
||||
elements.scroller.scrollTop = 200;
|
||||
|
||||
// Transforms don't affect offsetTop, so use getBoundingClientRect.
|
||||
const stickyElementOffset = elements.sticky.getBoundingClientRect().y -
|
||||
elements.scroller.getBoundingClientRect().y;
|
||||
assert_equals(stickyElementOffset, 25);
|
||||
}, 'Perspective transforms are carried out on the stuck element position');
|
||||
window.addEventListener('load', function() {
|
||||
document.getElementById('scroller1').scrollTop = 50;
|
||||
document.getElementById('scroller2').scrollTop = 50;
|
||||
document.getElementById('scroller3').scrollTop = 50;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller1" class="scroller">
|
||||
<div class="indicator box" style="height: 100px; top: 75px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container">
|
||||
<div class="sticky box" style="transform: scale(2);"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller2" class="scroller">
|
||||
<div class="rotated indicator" style="top: 100px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container" style="height: 250px;">
|
||||
<div class="rotated sticky"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="group">
|
||||
<div id="scroller3" class="scroller">
|
||||
<div class="perspective indicator" style="top: 100px;"></div>
|
||||
<div class="contents">
|
||||
<div class="container">
|
||||
<div class="perspective sticky"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>You should see three green boxes above. No red should be visible.</div>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
const gTestUrl = '../resources/1x1-green.png';
|
||||
const gTestUrl = '/media/1x1-green.png';
|
||||
const gBadTestUrl = document.location.href;
|
||||
|
||||
async_test(t => {
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
const gTestUrl = '../resources/1x1-green.png';
|
||||
const gTestUrl = '/media/1x1-green.png';
|
||||
const gBase64TestUrl = 'data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=';
|
||||
const gBadTestUrl = document.location.href;
|
||||
|
||||
|
|
|
@ -20,6 +20,16 @@ test(() => {
|
|||
'Fallback member should be null');
|
||||
}, 'CSSVariableReferenceValue can be constructed with no fallback');
|
||||
|
||||
test(() => {
|
||||
const result = new CSSVariableReferenceValue('--foo', null);
|
||||
|
||||
assert_not_equals(result, null,
|
||||
'A CSSVariableReferenceValue should be created');
|
||||
assert_equals(result.variable, '--foo',
|
||||
'Variable member should be same as passed in the constructor');
|
||||
assert_equals(result.fallback, null, 'Fallback member should be null');
|
||||
}, 'CSSVariableReferenceValue can be constructed with null fallback');
|
||||
|
||||
test(() => {
|
||||
const result = new CSSVariableReferenceValue('--foo',
|
||||
new CSSUnparsedValue(['lemon']));
|
||||
|
@ -32,7 +42,7 @@ test(() => {
|
|||
'Fallback member should not be null');
|
||||
assert_style_value_equals(result.fallback, new CSSUnparsedValue(['lemon']),
|
||||
'Fallback member should be as same as passed in the constructor');
|
||||
}, 'CSSVariableReferenceValue can be constructed with fallback');
|
||||
}, 'CSSVariableReferenceValue can be constructed with valid fallback');
|
||||
|
||||
test(() => {
|
||||
let result = new CSSVariableReferenceValue('--foo');
|
||||
|
|
|
@ -24,7 +24,7 @@ test(t => {
|
|||
|
||||
test(t => {
|
||||
const styleMap = createComputedStyleMap(t, 'width: 10px; transition-duration: 1s, 2s; height: 20px');
|
||||
assert_style_value_equals(findInStyleMap(styleMap, 'width'), CSS.px(10));
|
||||
assert_style_value_array_equals(findInStyleMap(styleMap, 'width'), [CSS.px(10)]);
|
||||
}, 'StylePropertyMap iterator returns CSS properties with the correct CSSStyleValue');
|
||||
|
||||
test(t => {
|
||||
|
@ -34,9 +34,9 @@ test(t => {
|
|||
|
||||
test(t => {
|
||||
const styleMap = createComputedStyleMap(t, '--A: A; --C: C; color: red; --B: B;');
|
||||
assert_style_value_equals(findInStyleMap(styleMap, '--A'), new CSSUnparsedValue([' A']));
|
||||
assert_style_value_equals(findInStyleMap(styleMap, '--B'), new CSSUnparsedValue([' B']));
|
||||
assert_style_value_equals(findInStyleMap(styleMap, '--C'), new CSSUnparsedValue([' C']));
|
||||
assert_style_value_array_equals(findInStyleMap(styleMap, '--A'), [new CSSUnparsedValue([' A'])]);
|
||||
assert_style_value_array_equals(findInStyleMap(styleMap, '--B'), [new CSSUnparsedValue([' B'])]);
|
||||
assert_style_value_array_equals(findInStyleMap(styleMap, '--C'), [new CSSUnparsedValue([' C'])]);
|
||||
}, 'StylePropertyMap iterator returns custom properties with the correct CSSStyleValue');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -25,7 +25,8 @@ test(t => {
|
|||
const keys = [...styleMap.keys()], values = [...styleMap.values()];
|
||||
|
||||
assert_array_equals(keys, ['height', 'width']);
|
||||
assert_style_value_array_equals(values, [CSS.px(5), CSS.px(10)]);
|
||||
assert_style_value_array_equals(values[0], [CSS.px(5)]);
|
||||
assert_style_value_array_equals(values[1], [CSS.px(10)]);
|
||||
}, 'StylePropertyMap iterator returns CSS properties with the correct CSSStyleValue');
|
||||
|
||||
test(t => {
|
||||
|
@ -41,11 +42,9 @@ test(t => {
|
|||
const keys = [...styleMap.keys()], values = [...styleMap.values()];
|
||||
|
||||
assert_array_equals(keys, ['--A', '--B', '--C']);
|
||||
assert_style_value_array_equals(values, [
|
||||
new CSSUnparsedValue([' A']),
|
||||
new CSSUnparsedValue([' B']),
|
||||
new CSSUnparsedValue([' C']),
|
||||
])
|
||||
assert_style_value_array_equals(values[0], [new CSSUnparsedValue([' A'])]);
|
||||
assert_style_value_array_equals(values[1], [new CSSUnparsedValue([' B'])]);
|
||||
assert_style_value_array_equals(values[2], [new CSSUnparsedValue([' C'])]);
|
||||
}, 'StylePropertyMap iterator returns custom properties with the correct CSSStyleValue');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -25,7 +25,8 @@ test(t => {
|
|||
const keys = [...styleMap.keys()], values = [...styleMap.values()];
|
||||
|
||||
assert_array_equals(keys, ['height', 'width']);
|
||||
assert_style_value_array_equals(values, [CSS.px(5), CSS.px(10)]);
|
||||
assert_style_value_array_equals(values[0], [CSS.px(5)]);
|
||||
assert_style_value_array_equals(values[1], [CSS.px(10)]);
|
||||
}, 'StylePropertyMap iterator returns CSS properties with the correct CSSStyleValue');
|
||||
|
||||
test(t => {
|
||||
|
@ -41,11 +42,9 @@ test(t => {
|
|||
const keys = [...styleMap.keys()], values = [...styleMap.values()];
|
||||
|
||||
assert_array_equals(keys, ['--A', '--B', '--C']);
|
||||
assert_style_value_array_equals(values, [
|
||||
new CSSUnparsedValue([' A']),
|
||||
new CSSUnparsedValue([' B']),
|
||||
new CSSUnparsedValue([' C']),
|
||||
])
|
||||
assert_style_value_array_equals(values[0], [new CSSUnparsedValue([' A'])]);
|
||||
assert_style_value_array_equals(values[1], [new CSSUnparsedValue([' B'])]);
|
||||
assert_style_value_array_equals(values[2], [new CSSUnparsedValue([' C'])]);
|
||||
}, 'StylePropertyMap iterator returns custom properties with the correct CSSStyleValue');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>'opacity' property</title>
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-get">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
|
||||
<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#property-stle-value-normalization">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../../resources/testhelper.js"></script>
|
||||
<script src="resources/testsuite.js"></script>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function assert_is_equal_with_clamping(input, result) {
|
||||
const number = input.to('number');
|
||||
|
||||
if (number.value < 0)
|
||||
assert_style_value_equals(result, new CSSUnitValue(0, 'number'));
|
||||
else if (number.value > 1)
|
||||
assert_style_value_equals(result, new CSSUnitValue(1, 'number'));
|
||||
else
|
||||
assert_style_value_equals(result, input);
|
||||
}
|
||||
|
||||
runPropertyTests('opacity', [
|
||||
{
|
||||
syntax: '<number>',
|
||||
computed: assert_is_equal_with_clamping
|
||||
},
|
||||
]);
|
||||
|
||||
</script>
|
|
@ -111,6 +111,31 @@ const gTestSyntaxExamples = {
|
|||
}
|
||||
],
|
||||
},
|
||||
'<number>': {
|
||||
description: 'a number',
|
||||
examples: [
|
||||
{
|
||||
description: 'the number zero',
|
||||
input: new CSSUnitValue(0, 'number')
|
||||
},
|
||||
{
|
||||
description: 'a negative number',
|
||||
input: new CSSUnitValue(-3.14, 'number')
|
||||
},
|
||||
{
|
||||
description: 'a positive number',
|
||||
input: new CSSUnitValue(3.14, 'number')
|
||||
},
|
||||
{
|
||||
description: "a calc number",
|
||||
input: new CSSMathSum(new CSSUnitValue(2, 'number'), new CSSUnitValue(3, 'number')),
|
||||
defaultSpecified: (_, result) => assert_is_calc_sum(result),
|
||||
defaultComputed: (_, result) => {
|
||||
assert_style_value_equals(result, new CSSUnitValue(5, 'number'));
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
'<position>': {
|
||||
description: 'a position',
|
||||
examples: [
|
||||
|
|
11
tests/wpt/web-platform-tests/images/colors.svg
Normal file
11
tests/wpt/web-platform-tests/images/colors.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="100" height="50">
|
||||
<style>use:not(:target) { display: none; }</style>
|
||||
<defs>
|
||||
<rect id="green-box" fill="#00ff00" width="100" height="50"/>
|
||||
<rect id="red-box" fill="#ff0000" width="100" height="50"/>
|
||||
</defs>
|
||||
<use id="green" xlink:href="#green-box"/>
|
||||
<use id="red" xlink:href="#red-box"/>
|
||||
</svg>
|
After Width: | Height: | Size: 411 B |
|
@ -7,37 +7,31 @@ interface CSSStyleValue {
|
|||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
|
||||
interface StylePropertyMapReadOnly {
|
||||
readonly maplike<DOMString, sequence<CSSStyleValue>>;
|
||||
iterable<DOMString, sequence<CSSStyleValue>>;
|
||||
any get(DOMString property);
|
||||
/* 'any' means (undefined or CSSStyleValue) here,
|
||||
see https://github.com/heycam/webidl/issues/60 */
|
||||
sequence<CSSStyleValue> getAll(DOMString property);
|
||||
boolean has(DOMString property);
|
||||
stringifier;
|
||||
readonly attribute long size;
|
||||
};
|
||||
|
||||
callback UpdateFunction = CSSStyleValue (CSSStyleValue oldValue);
|
||||
|
||||
[Exposed=Window]
|
||||
interface StylePropertyMap : StylePropertyMapReadOnly {
|
||||
maplike<DOMString, sequence<CSSStyleValue>>;
|
||||
void set(DOMString property, (CSSStyleValue or DOMString)... values);
|
||||
void append(DOMString property, (CSSStyleValue or DOMString)... values);
|
||||
void delete(DOMString property);
|
||||
void set(DOMString property, (CSSStyleValue or DOMString)... values);
|
||||
void clear();
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
|
||||
partial interface Element {
|
||||
StylePropertyMapReadOnly computedStyleMap();
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
|
||||
partial interface CSSStyleRule {
|
||||
[SameObject] readonly attribute StylePropertyMap styleMap;
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]
|
||||
partial interface ElementCSSInlineStyle {
|
||||
[SameObject] readonly attribute StylePropertyMap attributeStyleMap;
|
||||
};
|
||||
|
@ -54,7 +48,7 @@ interface CSSUnparsedValue : CSSStyleValue {
|
|||
typedef (DOMString or CSSVariableReferenceValue) CSSUnparsedSegment;
|
||||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet),
|
||||
Constructor(DOMString variable, optional CSSUnparsedValue fallback)]
|
||||
Constructor(DOMString variable, optional CSSUnparsedValue? fallback = null)]
|
||||
interface CSSVariableReferenceValue {
|
||||
attribute DOMString variable;
|
||||
readonly attribute CSSUnparsedValue? fallback;
|
||||
|
@ -66,8 +60,6 @@ interface CSSKeywordValue : CSSStyleValue {
|
|||
attribute DOMString value;
|
||||
};
|
||||
|
||||
typedef (DOMString or CSSKeywordValue) CSSKeywordish;
|
||||
|
||||
typedef (double or CSSNumericValue) CSSNumberish;
|
||||
|
||||
enum CSSNumericBaseType {
|
||||
|
@ -306,7 +298,7 @@ interface CSSMatrixComponent : CSSTransformComponent {
|
|||
};
|
||||
|
||||
dictionary CSSMatrixComponentOptions {
|
||||
boolean is2D = false;
|
||||
boolean is2D;
|
||||
};
|
||||
|
||||
[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet),
|
||||
|
|
|
@ -340,7 +340,7 @@ interface Element : Node {
|
|||
attribute DOMString id;
|
||||
attribute DOMString className;
|
||||
[SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
|
||||
attribute DOMString slot;
|
||||
[Unscopable] attribute DOMString slot;
|
||||
|
||||
boolean hasAttributes();
|
||||
[SameObject] readonly attribute NamedNodeMap attributes;
|
||||
|
|
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 135 B |
|
@ -3,7 +3,6 @@
|
|||
<title>PerformanceObservers: navigation</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="performanceobservers.js"></script>
|
||||
<h1>PerformanceObservers: navigation</h1>
|
||||
<p>
|
||||
Navigation will <a href="https://w3c.github.io/performance-timeline/#dfn-queue-a-performanceentry">queue a PerformanceEntry</a>.
|
||||
|
@ -11,14 +10,16 @@ Navigation will <a href="https://w3c.github.io/performance-timeline/#dfn-queue-a
|
|||
<div id="log"></div>
|
||||
<script>
|
||||
async_test(function (t) {
|
||||
function checkEntry(pes) {
|
||||
assert_equals(pes.length, 1, "Only one navigation timing entry");
|
||||
assert_equals(pes[0].entryType, "navigation", "entryType is \"navigation\"");
|
||||
assert_equals(pes[0].name, window.location.toString(), "name is the address of the document");
|
||||
}
|
||||
var observer = new PerformanceObserver(
|
||||
t.step_func(function (entryList, obs) {
|
||||
checkEntries(entryList.getEntries(),
|
||||
[{ entryType: "navigation", name: "document"}]);
|
||||
checkEntries(entryList.getEntriesByType("navigation"),
|
||||
[{ entryType: "navigation", name: "document"}]);
|
||||
checkEntries(entryList.getEntriesByName("document"),
|
||||
[{ entryType: "navigation", name: "document"}]);
|
||||
checkEntry(entryList.getEntries());
|
||||
checkEntry(entryList.getEntriesByType("navigation"));
|
||||
checkEntry(entryList.getEntriesByName(window.location.toString()));
|
||||
observer.disconnect();
|
||||
t.done();
|
||||
})
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/preload/issues/120">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/preload/resources/preload_helper.js"></script>
|
||||
<script>
|
||||
var t = async_test('Makes sure that Link headers preload images with (experimental) srcset/imgsizes attributes.');
|
||||
</script>
|
||||
<body>
|
||||
<script src="resources/dummy.js?pipe=trickle(d3)&link-header-preload-srcset"></script>
|
||||
<script>
|
||||
window.addEventListener("load", t.step_func(function() {
|
||||
verifyPreloadAndRTSupport();
|
||||
verifyNumberOfDownloads('resources/square.png?1x', 1);
|
||||
verifyNumberOfDownloads('resources/square.png?2x', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?3x', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?base', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?200', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?400', 1);
|
||||
verifyNumberOfDownloads('resources/square.png?800', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?150', 0);
|
||||
verifyNumberOfDownloads('resources/square.png?300', 1);
|
||||
verifyNumberOfDownloads('resources/square.png?600', 0);
|
||||
t.done();
|
||||
}));
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,3 @@
|
|||
Link: <resources/square.png?1x>; rel=preload; as=image; srcset="resources/square.png?2x 2x, resources/square.png?3x 3x"
|
||||
Link: <resources/square.png?base>; rel=preload; as=image; srcset="resources/square.png?200 200w, resources/square.png?400 400w, resources/square.png?800 800w"; imgsizes=400px
|
||||
Link: <resources/square.png?base>; rel=preload; as=image; srcset="resources/square.png?150 150w, resources/square.png?300 300w, resources/square.png?600 600w"; imgsizes="(min-width: 300px) 300px, 150px"
|
|
@ -1007,6 +1007,13 @@ IdlInterface.prototype.has_constants = function()
|
|||
};
|
||||
//@}
|
||||
|
||||
IdlInterface.prototype.get_unscopables = function()
|
||||
{
|
||||
return this.members.filter(function(member) {
|
||||
return member.isUnscopable;
|
||||
});
|
||||
};
|
||||
|
||||
IdlInterface.prototype.is_global = function()
|
||||
//@{
|
||||
{
|
||||
|
@ -1552,6 +1559,69 @@ IdlInterface.prototype.test_self = function()
|
|||
assert_equals(self[this.name].prototype.constructor, self[this.name],
|
||||
this.name + '.prototype.constructor is not the same object as ' + this.name);
|
||||
}.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');
|
||||
|
||||
|
||||
test(function()
|
||||
{
|
||||
if (this.is_callback() && !this.has_constants()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_own_property(self, this.name,
|
||||
"self does not have own property " + format_value(this.name));
|
||||
|
||||
if (this.is_callback()) {
|
||||
assert_false("prototype" in self[this.name],
|
||||
this.name + ' should not have a "prototype" property');
|
||||
return;
|
||||
}
|
||||
|
||||
assert_own_property(self[this.name], "prototype",
|
||||
'interface "' + this.name + '" does not have own property "prototype"');
|
||||
|
||||
// If the interface has any member declared with the [Unscopable] extended
|
||||
// attribute, then there must be a property on the interface prototype object
|
||||
// whose name is the @@unscopables symbol, which has the attributes
|
||||
// { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true },
|
||||
// and whose value is an object created as follows...
|
||||
var unscopables = this.get_unscopables().map(m => m.name);
|
||||
var proto = self[this.name].prototype;
|
||||
if (unscopables.length != 0) {
|
||||
assert_own_property(
|
||||
proto, Symbol.unscopables,
|
||||
this.name + '.prototype should have an @@unscopables property');
|
||||
var desc = Object.getOwnPropertyDescriptor(proto, Symbol.unscopables);
|
||||
assert_false("get" in desc,
|
||||
this.name + ".prototype[Symbol.unscopables] should not have a getter");
|
||||
assert_false("set" in desc, this.name + ".prototype[Symbol.unscopables] should not have a setter");
|
||||
assert_false(desc.writable, this.name + ".prototype[Symbol.unscopables] should not be writable");
|
||||
assert_false(desc.enumerable, this.name + ".prototype[Symbol.unscopables] should not be enumerable");
|
||||
assert_true(desc.configurable, this.name + ".prototype[Symbol.unscopables] should be configurable");
|
||||
assert_equals(desc.value, proto[Symbol.unscopables],
|
||||
this.name + '.prototype[Symbol.unscopables] should be in the descriptor');
|
||||
assert_equals(typeof desc.value, "object",
|
||||
this.name + '.prototype[Symbol.unscopables] should be an object');
|
||||
assert_equals(Object.getPrototypeOf(desc.value), null,
|
||||
this.name + '.prototype[Symbol.unscopables] should have a null prototype');
|
||||
assert_equals(Object.getOwnPropertySymbols(desc.value).length,
|
||||
0,
|
||||
this.name + '.prototype[Symbol.unscopables] should have the right number of symbol-named properties');
|
||||
|
||||
// Check that we do not have _extra_ unscopables. Checking that we
|
||||
// have all the ones we should will happen in the per-member tests.
|
||||
var observed = Object.getOwnPropertyNames(desc.value);
|
||||
for (var prop of observed) {
|
||||
assert_not_equals(unscopables.indexOf(prop),
|
||||
-1,
|
||||
this.name + '.prototype[Symbol.unscopables] has unexpected property "' + prop + '"');
|
||||
}
|
||||
} else {
|
||||
assert_equals(Object.getOwnPropertyDescriptor(self[this.name].prototype, Symbol.unscopables),
|
||||
undefined,
|
||||
this.name + '.prototype should not have @@unscopables');
|
||||
}
|
||||
}.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s @@unscopables property');
|
||||
|
||||
};
|
||||
|
||||
//@}
|
||||
|
@ -1805,6 +1875,10 @@ IdlInterface.prototype.test_member_attribute = function(member)
|
|||
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
test(function () {
|
||||
this.do_member_unscopable_asserts(member);
|
||||
}.bind(this), 'Unscopable handled correctly for ' + member.name + ' property on ' + this.name);
|
||||
};
|
||||
|
||||
//@}
|
||||
|
@ -1869,6 +1943,41 @@ IdlInterface.prototype.test_member_operation = function(member)
|
|||
}
|
||||
this.do_member_operation_asserts(memberHolderObject, member, a_test);
|
||||
}.bind(this));
|
||||
|
||||
test(function () {
|
||||
this.do_member_unscopable_asserts(member);
|
||||
}.bind(this),
|
||||
'Unscopable handled correctly for ' + member.name + "(" +
|
||||
member.arguments.map(
|
||||
function(m) {return m.idlType.idlType; } ).join(", ")
|
||||
+ ")" + ' on ' + this.name);
|
||||
};
|
||||
|
||||
IdlInterface.prototype.do_member_unscopable_asserts = function(member)
|
||||
{
|
||||
// Check that if the member is unscopable then it's in the
|
||||
// @@unscopables object properly.
|
||||
if (!member.isUnscopable) {
|
||||
return;
|
||||
}
|
||||
|
||||
var unscopables = self[this.name].prototype[Symbol.unscopables];
|
||||
var prop = member.name;
|
||||
var propDesc = Object.getOwnPropertyDescriptor(unscopables, prop);
|
||||
assert_equals(typeof propDesc, "object",
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must exist')
|
||||
assert_false("get" in propDesc,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no getter');
|
||||
assert_false("set" in propDesc,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must have no setter');
|
||||
assert_true(propDesc.writable,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must be writable');
|
||||
assert_true(propDesc.enumerable,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must be enumerable');
|
||||
assert_true(propDesc.configurable,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must be configurable');
|
||||
assert_equals(propDesc.value, true,
|
||||
this.name + '.prototype[Symbol.unscopables].' + prop + ' must have the value `true`');
|
||||
};
|
||||
|
||||
//@}
|
||||
|
@ -2552,6 +2661,7 @@ function IdlInterfaceMember(obj)
|
|||
}
|
||||
|
||||
this.isUnforgeable = this.has_extended_attribute("Unforgeable");
|
||||
this.isUnscopable = this.has_extended_attribute("Unscopable");
|
||||
}
|
||||
|
||||
//@}
|
||||
|
|
|
@ -82,6 +82,13 @@ idlArray.test();
|
|||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Foo interface: existence and properties of interface prototype object's @@unscopables property",
|
||||
"status_string": "PASS",
|
||||
"properties": {},
|
||||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Foo interface: internal [[SetPrototypeOf]] method of global platform object - setting to a new value via Object.setPrototypeOf should throw a TypeError",
|
||||
"status_string": "FAIL",
|
||||
|
@ -222,6 +229,13 @@ idlArray.test();
|
|||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Window interface: existence and properties of interface prototype object's @@unscopables property",
|
||||
"status_string": "PASS",
|
||||
"properties": {},
|
||||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Window interface: internal [[SetPrototypeOf]] method of global platform object - setting to a new value via Object.setPrototypeOf should throw a TypeError",
|
||||
"status_string": "PASS",
|
||||
|
|
|
@ -89,6 +89,13 @@ idlArray.test();
|
|||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Foo interface: existence and properties of interface prototype object's @@unscopables property",
|
||||
"status_string": "PASS",
|
||||
"properties": {},
|
||||
"message": null,
|
||||
"stack": null
|
||||
},
|
||||
{
|
||||
"name": "Foo must be primary interface of new Foo()",
|
||||
"status_string": "PASS",
|
||||
|
|
|
@ -18,6 +18,6 @@ def main(request, response):
|
|||
headers.append(('Access-Control-Allow-Origin', '*'))
|
||||
|
||||
image_path = os.path.join(request.doc_root, 'images')
|
||||
body = create_part(os.path.join(image_path, 'green-1x1.png'))
|
||||
body = create_part(os.path.join(image_path, 'red.png'))
|
||||
body = body + create_part(os.path.join(image_path, 'red-16x16.png'))
|
||||
return headers, body
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
addEventListener('fetch', evt => {
|
||||
evt.respondWith(fetch(evt.request));
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<img src="/images/green.svg">
|
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Green svg box reference file</title>
|
||||
<p>Pass if you see a green box below.</p>
|
||||
<iframe src="svg-target-reftest-001-frame.html">
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<img src="/images/colors.svg#green">
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<meta charset="utf-8">
|
||||
<title>Service worker interception does not break SVG fragment targets</title>
|
||||
<meta name="assert" content="SVG with link fragment should render correctly when intercepted by a service worker.">
|
||||
<script src="resources/test-helpers.sub.js"></script>
|
||||
<link rel="match" href="resources/svg-target-reftest-001.html">
|
||||
<p>Pass if you see a green box below.</p>
|
||||
<script>
|
||||
// We want to use utility functions designed for testharness.js where
|
||||
// there is a test object. We don't have a test object in reftests
|
||||
// so fake one for now.
|
||||
const fake_test = { step_func: f => f };
|
||||
|
||||
async function runTest() {
|
||||
const script = './resources/pass-through-worker.js';
|
||||
const scope = './resources/svg-target-reftest-frame.html';
|
||||
let reg = await navigator.serviceWorker.register(script, { scope });
|
||||
await wait_for_state(fake_test, reg.installing, 'activated');
|
||||
let f = await with_iframe(scope);
|
||||
document.documentElement.classList.remove('reftest-wait');
|
||||
await reg.unregister();
|
||||
// Note, we cannot remove the frame explicitly because we can't
|
||||
// tell when the reftest completes.
|
||||
}
|
||||
runTest();
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Should not crash on circular filter reference containing a foreignObject.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>test(()=>{})</script>
|
||||
<svg id="svg" filter="url(#filter)">
|
||||
<foreignObject overflow="hidden"></foreignObject>
|
||||
</svg>
|
||||
<svg>
|
||||
<filter id="filter">
|
||||
<feImage xlink:href="#svg"></feImage>
|
||||
</filter>
|
||||
</svg>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Should not crash on circular filter reference containing an svg under svg.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>test(()=>{})</script>
|
||||
<svg id="svg" filter="url(#filter)">
|
||||
<filter id="filter">
|
||||
<feImage xlink:href="#svg"></feImage>
|
||||
</filter>
|
||||
<svg overflow="hidden" width="20" height="20">
|
||||
<rect fill="black" width="20" height="20"></rect>
|
||||
</svg>
|
||||
</svg>
|
|
@ -1,6 +1,5 @@
|
|||
@AutomatedTester
|
||||
@andreastt
|
||||
@lukeis
|
||||
@mjzffr
|
||||
@shs96c
|
||||
@whimboo
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import pytest
|
||||
|
||||
from tests.support.asserts import assert_error, assert_same_element, assert_success
|
||||
from tests.support.asserts import (
|
||||
assert_element_has_focus,
|
||||
assert_error,
|
||||
assert_same_element,
|
||||
assert_success,
|
||||
)
|
||||
from tests.support.inline import inline
|
||||
|
||||
|
||||
|
@ -17,7 +22,7 @@ def add_event_listeners(element):
|
|||
element.session.execute_script("""
|
||||
let [target] = arguments;
|
||||
window.events = [];
|
||||
for (let expected of ["focus", "blur", "change", "keypress", "keydown", "keyup", "input"]) {
|
||||
for (let expected of ["focus", "change", "keypress", "keydown", "keyup", "input"]) {
|
||||
target.addEventListener(expected, ({type}) => window.events.push(type));
|
||||
}
|
||||
""", args=(element,))
|
||||
|
@ -34,6 +39,7 @@ def test_input(session):
|
|||
|
||||
element_send_keys(session, element, "foo")
|
||||
assert element.property("value") == "foo"
|
||||
assert_element_has_focus(element)
|
||||
|
||||
|
||||
def test_textarea(session):
|
||||
|
@ -43,6 +49,7 @@ def test_textarea(session):
|
|||
|
||||
element_send_keys(session, element, "foo")
|
||||
assert element.property("value") == "foo"
|
||||
assert_element_has_focus(element)
|
||||
|
||||
|
||||
def test_input_append(session):
|
||||
|
@ -89,6 +96,13 @@ def test_events(session, tag):
|
|||
"keydown",
|
||||
"keypress",
|
||||
"input",
|
||||
"keyup",
|
||||
"change",
|
||||
"blur"]
|
||||
"keyup"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("tag", ["input", "textarea"])
|
||||
def test_not_blurred(session, tag):
|
||||
session.url = inline("<%s>" % tag)
|
||||
element = session.find.css(tag, all=False)
|
||||
|
||||
element_send_keys(session, element, "")
|
||||
assert_element_has_focus(element)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from tests.support.asserts import assert_error, assert_same_element, assert_success
|
||||
from tests.support.asserts import assert_error, assert_success
|
||||
from tests.support.inline import iframe, inline
|
||||
|
||||
|
||||
|
@ -13,8 +13,8 @@ def send_keys_to_element(session, element, text):
|
|||
|
||||
def test_body_is_interactable(session):
|
||||
session.url = inline("""
|
||||
<body onkeypress="document.getElementById('result').value += event.key">
|
||||
<input type="text" id="result"/>
|
||||
<body onkeypress="document.querySelector('input').value += event.key">
|
||||
<input>
|
||||
</body>
|
||||
""")
|
||||
|
||||
|
@ -22,18 +22,18 @@ def test_body_is_interactable(session):
|
|||
result = session.find.css("input", all=False)
|
||||
|
||||
# By default body is the active element
|
||||
assert_same_element(session, element, session.active_element)
|
||||
assert session.active_element is element
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
assert_success(response)
|
||||
assert_same_element(session, element, session.active_element)
|
||||
assert session.active_element is element
|
||||
assert result.property("value") == "foo"
|
||||
|
||||
|
||||
def test_document_element_is_interactable(session):
|
||||
session.url = inline("""
|
||||
<html onkeypress="document.getElementById('result').value += event.key">
|
||||
<input type="text" id="result"/>
|
||||
<html onkeypress="document.querySelector('input').value += event.key">
|
||||
<input>
|
||||
</html>
|
||||
""")
|
||||
|
||||
|
@ -42,18 +42,18 @@ def test_document_element_is_interactable(session):
|
|||
result = session.find.css("input", all=False)
|
||||
|
||||
# By default body is the active element
|
||||
assert_same_element(session, body, session.active_element)
|
||||
assert session.active_element is body
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
assert_success(response)
|
||||
assert_same_element(session, body, session.active_element)
|
||||
assert session.active_element is element
|
||||
assert result.property("value") == "foo"
|
||||
|
||||
|
||||
def test_iframe_is_interactable(session):
|
||||
session.url = inline(iframe("""
|
||||
<body onkeypress="document.getElementById('result').value += event.key">
|
||||
<input type="text" id="result"/>
|
||||
<body onkeypress="document.querySelector('input').value += event.key">
|
||||
<input>
|
||||
</body>
|
||||
"""))
|
||||
|
||||
|
@ -61,11 +61,11 @@ def test_iframe_is_interactable(session):
|
|||
frame = session.find.css("iframe", all=False)
|
||||
|
||||
# By default the body has the focus
|
||||
assert_same_element(session, body, session.active_element)
|
||||
assert session.active_element is body
|
||||
|
||||
response = send_keys_to_element(session, frame, "foo")
|
||||
assert_success(response)
|
||||
assert_same_element(session, body, session.active_element)
|
||||
assert session.active_element is frame
|
||||
|
||||
# Any key events are immediately routed to the nested
|
||||
# browsing context's active document.
|
||||
|
@ -75,7 +75,7 @@ def test_iframe_is_interactable(session):
|
|||
|
||||
|
||||
def test_transparent_element(session):
|
||||
session.url = inline("<input style=\"opacity: 0;\">")
|
||||
session.url = inline("""<input style="opacity: 0">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
|
@ -94,8 +94,8 @@ def test_readonly_element(session):
|
|||
|
||||
def test_obscured_element(session):
|
||||
session.url = inline("""
|
||||
<input type="text" />
|
||||
<div style="position: relative; top: -3em; height: 5em; background-color: blue"></div>
|
||||
<input>
|
||||
<div style="position: relative; top: -3em; height: 5em; background: blue;"></div>
|
||||
""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
|
@ -113,7 +113,7 @@ def test_not_a_focusable_element(session):
|
|||
|
||||
|
||||
def test_not_displayed_element(session):
|
||||
session.url = inline("<input style=\"display: none\">")
|
||||
session.url = inline("""<input style="display: none">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
|
@ -121,7 +121,7 @@ def test_not_displayed_element(session):
|
|||
|
||||
|
||||
def test_hidden_element(session):
|
||||
session.url = inline("<input style=\"visibility: hidden\">")
|
||||
session.url = inline("""<input style="visibility: hidden">""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
|
@ -129,7 +129,7 @@ def test_hidden_element(session):
|
|||
|
||||
|
||||
def test_disabled_element(session):
|
||||
session.url = inline("<input disabled=\"false\">")
|
||||
session.url = inline("""<input disabled>""")
|
||||
element = session.find.css("input", all=False)
|
||||
|
||||
response = send_keys_to_element(session, element, "foo")
|
||||
|
|
|
@ -161,9 +161,8 @@ def test_element(session):
|
|||
session.url = inline("<input type=checkbox>")
|
||||
element = session.find.css("input", all=False)
|
||||
element.click()
|
||||
assert None == session.execute_script("return arguments[0].hasAttribute('checked')",
|
||||
args=[element])
|
||||
result = session.transport.send("GET", "session/{session_id}/element/{element_id}/property/id"
|
||||
assert session.execute_script("return arguments[0].hasAttribute('checked')", args=(element,)) is False
|
||||
result = session.transport.send("GET", "session/{session_id}/element/{element_id}/property/checked"
|
||||
.format(session_id=session.session_id,
|
||||
element_id=element.id))
|
||||
assert_success(result, True)
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 320px;
|
||||
height: 240px;
|
||||
}
|
||||
.cue {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cue.center {
|
||||
text-align: center;
|
||||
}
|
||||
.cue > span {
|
||||
font-family: sans-serif;
|
||||
background: green;
|
||||
color: green;
|
||||
font-size: 50px;
|
||||
padding: 2px;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
</video>
|
||||
<div class="cue center"><span>אבג</span></div>
|
||||
</div>
|
||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<link rel="match" href="track-cue-rendering-position-align-rtl-center-ref.html">
|
||||
<script>
|
||||
function addTrackWithRtlCueData(video, cueData) {
|
||||
var track = video.addTextTrack('subtitles');
|
||||
var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
|
||||
for (var prop in cueData)
|
||||
cue[prop] = cueData[prop];
|
||||
track.addCue(cue);
|
||||
track.mode = 'showing';
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
video::cue {
|
||||
font-size: 50px;
|
||||
color: green;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
<script>
|
||||
var video = document.currentScript.parentNode;
|
||||
addTrackWithRtlCueData(video, { position: 50, positionAlign: 'center', align: 'center', size: 50, line: 0 });
|
||||
</script>
|
||||
</video>
|
||||
</html>
|
|
@ -1,36 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 320px;
|
||||
height: 240px;
|
||||
}
|
||||
.cue {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cue.start {
|
||||
text-align: end;
|
||||
}
|
||||
.cue > span {
|
||||
font-family: sans-serif;
|
||||
background: green;
|
||||
color: green;
|
||||
font-size: 50px;
|
||||
padding: 2px;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
</video>
|
||||
<div class="cue start"><span>אבג</span></div>
|
||||
</div>
|
||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<link rel="match" href="track-cue-rendering-position-align-rtl-line-left-ref.html">
|
||||
<script>
|
||||
function addTrackWithRtlCueData(video, cueData) {
|
||||
var track = video.addTextTrack('subtitles');
|
||||
var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
|
||||
for (var prop in cueData)
|
||||
cue[prop] = cueData[prop];
|
||||
track.addCue(cue);
|
||||
track.mode = 'showing';
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
video::cue {
|
||||
font-size: 50px;
|
||||
color: green;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
<script>
|
||||
var video = document.currentScript.parentNode;
|
||||
addTrackWithRtlCueData(video, { position: 50, positionAlign: 'line-left', align: 'start', size: 50, line: 0 });
|
||||
</script>
|
||||
</video>
|
||||
</html>
|
|
@ -1,36 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 320px;
|
||||
height: 240px;
|
||||
}
|
||||
.cue {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cue.end {
|
||||
text-align: start;
|
||||
}
|
||||
.cue > span {
|
||||
font-family: sans-serif;
|
||||
background: green;
|
||||
color: green;
|
||||
font-size: 50px;
|
||||
padding: 2px;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
</video>
|
||||
<div class="cue end"><span>אבג</span></div>
|
||||
</div>
|
||||
</html>
|
|
@ -1,30 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<link rel="match" href="track-cue-rendering-position-align-rtl-line-right-ref.html">
|
||||
<script>
|
||||
function addTrackWithRtlCueData(video, cueData) {
|
||||
var track = video.addTextTrack('subtitles');
|
||||
var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
|
||||
for (var prop in cueData)
|
||||
cue[prop] = cueData[prop];
|
||||
track.addCue(cue);
|
||||
track.mode = 'showing';
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
video::cue {
|
||||
font-size: 50px;
|
||||
color: green;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
|
||||
<source src="/media/white.webm" type="video/webm">
|
||||
<source src="/media/white.mp4" type="video/mp4">
|
||||
<script>
|
||||
var video = document.currentScript.parentNode;
|
||||
addTrackWithRtlCueData(video, { position: 50, positionAlign: 'line-right', align: 'end', size: 50, line: 0 });
|
||||
</script>
|
||||
</video>
|
||||
</html>
|
|
@ -1,8 +1,9 @@
|
|||
"use strict";
|
||||
importScripts("/resources/testharness.js");
|
||||
|
||||
var name = "something else";
|
||||
|
||||
// This just makes the test name not "Untitled"
|
||||
test(() => { }, "Declaring name as an accidental global must not cause a harness error");
|
||||
test(() => { }, `Declaring name as an accidental global must not cause a harness error for ${self.constructor.name}`);
|
||||
|
||||
done();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue