mirror of
https://github.com/servo/servo.git
synced 2025-06-28 19:13:41 +01:00
Auto merge of #10777 - servo:wpt-20160421, r=Ms2ger
Update web-platform-tests to revision 0a518aaff73532a26e175789f7e75fa99593ac64 <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10777) <!-- Reviewable:end -->
This commit is contained in:
commit
1eec5d9f72
92 changed files with 2869 additions and 642 deletions
|
@ -1,5 +0,0 @@
|
||||||
[EventObject.after.dispatchEvent.html]
|
|
||||||
type: testharness
|
|
||||||
[Test Description: As the final step of the event dispatch, the implementation must reset the event object's default-action-prevention state. ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[EventObject.after.dispatchEvent.html]
|
|
||||||
type: testharness
|
|
||||||
[Test Description: As the final step of the event dispatch, the implementation must reset the event object's default-action-prevention state. ]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -42,6 +42,11 @@
|
||||||
[Array with mixed types]
|
[Array with mixed types]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[no-argument Blob constructor without 'new']
|
[Blob constructor with no arguments, without 'new']
|
||||||
|
bug: https://github.com/servo/servo/issues/10744
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Blob constructor with undefined as first argument]
|
||||||
|
bug: https://github.com/servo/servo/issues/10779
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -3225,6 +3225,14 @@
|
||||||
"path": "touch-events/single-touch-manual.html",
|
"path": "touch-events/single-touch-manual.html",
|
||||||
"url": "/touch-events/single-touch-manual.html"
|
"url": "/touch-events/single-touch-manual.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "uievents/order-of-events/focus-events/focus-manual.html",
|
||||||
|
"url": "/uievents/order-of-events/focus-events/focus-manual.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "uievents/order-of-events/focus-events/legacy-manual.html",
|
||||||
|
"url": "/uievents/order-of-events/focus-events/legacy-manual.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "uievents/order-of-events/mouse-events/click-on-body-manual.html",
|
"path": "uievents/order-of-events/mouse-events/click-on-body-manual.html",
|
||||||
"url": "/uievents/order-of-events/mouse-events/click-on-body-manual.html"
|
"url": "/uievents/order-of-events/mouse-events/click-on-body-manual.html"
|
||||||
|
@ -3695,6 +3703,56 @@
|
||||||
],
|
],
|
||||||
"url": "/compat/webkit-text-fill-color-property-001d.html"
|
"url": "/compat/webkit-text-fill-color-property-001d.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-002.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-002-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-002.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-003.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-003-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-003.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-004.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-004-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-004.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-005.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-005-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-005.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-006.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-006-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-006.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html",
|
"path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html",
|
||||||
"references": [
|
"references": [
|
||||||
|
@ -11067,10 +11125,6 @@
|
||||||
"path": "DOMEvents/tests/approved/EventListener.eventHandler.html",
|
"path": "DOMEvents/tests/approved/EventListener.eventHandler.html",
|
||||||
"url": "/DOMEvents/tests/approved/EventListener.eventHandler.html"
|
"url": "/DOMEvents/tests/approved/EventListener.eventHandler.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "DOMEvents/tests/approved/EventObject.after.dispatchEvent.html",
|
|
||||||
"url": "/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html",
|
"path": "DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html",
|
||||||
"url": "/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html"
|
"url": "/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html"
|
||||||
|
@ -11107,10 +11161,6 @@
|
||||||
"path": "DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html",
|
"path": "DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html",
|
||||||
"url": "/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html"
|
"url": "/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html",
|
|
||||||
"url": "/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html",
|
"path": "DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html",
|
||||||
"url": "/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html"
|
"url": "/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html"
|
||||||
|
@ -14047,6 +14097,10 @@
|
||||||
"path": "dom/events/Event-constructors.html",
|
"path": "dom/events/Event-constructors.html",
|
||||||
"url": "/dom/events/Event-constructors.html"
|
"url": "/dom/events/Event-constructors.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "dom/events/Event-defaultPrevented-after-dispatch.html",
|
||||||
|
"url": "/dom/events/Event-defaultPrevented-after-dispatch.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "dom/events/Event-defaultPrevented.html",
|
"path": "dom/events/Event-defaultPrevented.html",
|
||||||
"url": "/dom/events/Event-defaultPrevented.html"
|
"url": "/dom/events/Event-defaultPrevented.html"
|
||||||
|
@ -18731,6 +18785,10 @@
|
||||||
"path": "html/semantics/embedded-content/the-embed-element/embed-document.html",
|
"path": "html/semantics/embedded-content/the-embed-element/embed-document.html",
|
||||||
"url": "/html/semantics/embedded-content/the-embed-element/embed-document.html"
|
"url": "/html/semantics/embedded-content/the-embed-element/embed-document.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html",
|
||||||
|
"url": "/html/semantics/embedded-content/the-embed-element/embed-ignored-in-media-element.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm",
|
"path": "html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm",
|
||||||
"url": "/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm"
|
"url": "/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm"
|
||||||
|
@ -19991,6 +20049,22 @@
|
||||||
"path": "html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html",
|
"path": "html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html",
|
||||||
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html"
|
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-1.html",
|
||||||
|
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-1.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-2.html",
|
||||||
|
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-2.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-3.html",
|
||||||
|
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-3.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-4.html",
|
||||||
|
"url": "/html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-4.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html",
|
"path": "html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html",
|
||||||
"url": "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html"
|
"url": "/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html"
|
||||||
|
@ -28719,10 +28793,18 @@
|
||||||
"path": "web-animations/animation-effect-timing/duration.html",
|
"path": "web-animations/animation-effect-timing/duration.html",
|
||||||
"url": "/web-animations/animation-effect-timing/duration.html"
|
"url": "/web-animations/animation-effect-timing/duration.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation-effect-timing/easing.html",
|
||||||
|
"url": "/web-animations/animation-effect-timing/easing.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "web-animations/animation-effect-timing/endDelay.html",
|
"path": "web-animations/animation-effect-timing/endDelay.html",
|
||||||
"url": "/web-animations/animation-effect-timing/endDelay.html"
|
"url": "/web-animations/animation-effect-timing/endDelay.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation-effect-timing/fill.html",
|
||||||
|
"url": "/web-animations/animation-effect-timing/fill.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "web-animations/animation-effect-timing/getAnimations.html",
|
"path": "web-animations/animation-effect-timing/getAnimations.html",
|
||||||
"url": "/web-animations/animation-effect-timing/getAnimations.html"
|
"url": "/web-animations/animation-effect-timing/getAnimations.html"
|
||||||
|
@ -28739,6 +28821,18 @@
|
||||||
"path": "web-animations/animation-effect-timing/iterations.html",
|
"path": "web-animations/animation-effect-timing/iterations.html",
|
||||||
"url": "/web-animations/animation-effect-timing/iterations.html"
|
"url": "/web-animations/animation-effect-timing/iterations.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation-model/animation-types/discrete-animation.html",
|
||||||
|
"url": "/web-animations/animation-model/animation-types/discrete-animation.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation-model/animation-types/not-animatable.html",
|
||||||
|
"url": "/web-animations/animation-model/animation-types/not-animatable.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation-model/keyframes/effect-value-context.html",
|
||||||
|
"url": "/web-animations/animation-model/keyframes/effect-value-context.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "web-animations/animation-timeline/document-timeline.html",
|
"path": "web-animations/animation-timeline/document-timeline.html",
|
||||||
"url": "/web-animations/animation-timeline/document-timeline.html"
|
"url": "/web-animations/animation-timeline/document-timeline.html"
|
||||||
|
@ -28759,6 +28853,26 @@
|
||||||
"path": "web-animations/animation/finish.html",
|
"path": "web-animations/animation/finish.html",
|
||||||
"url": "/web-animations/animation/finish.html"
|
"url": "/web-animations/animation/finish.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/finished.html",
|
||||||
|
"url": "/web-animations/animation/finished.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/id.html",
|
||||||
|
"url": "/web-animations/animation/id.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/oncancel.html",
|
||||||
|
"url": "/web-animations/animation/oncancel.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/onfinish.html",
|
||||||
|
"url": "/web-animations/animation/onfinish.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/pause.html",
|
||||||
|
"url": "/web-animations/animation/pause.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "web-animations/animation/play.html",
|
"path": "web-animations/animation/play.html",
|
||||||
"url": "/web-animations/animation/play.html"
|
"url": "/web-animations/animation/play.html"
|
||||||
|
@ -28771,6 +28885,14 @@
|
||||||
"path": "web-animations/animation/playbackRate.html",
|
"path": "web-animations/animation/playbackRate.html",
|
||||||
"url": "/web-animations/animation/playbackRate.html"
|
"url": "/web-animations/animation/playbackRate.html"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/ready.html",
|
||||||
|
"url": "/web-animations/animation/ready.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "web-animations/animation/reverse.html",
|
||||||
|
"url": "/web-animations/animation/reverse.html"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "web-animations/keyframe-effect/constructor.html",
|
"path": "web-animations/keyframe-effect/constructor.html",
|
||||||
"url": "/web-animations/keyframe-effect/constructor.html"
|
"url": "/web-animations/keyframe-effect/constructor.html"
|
||||||
|
@ -35091,6 +35213,7 @@
|
||||||
},
|
},
|
||||||
"local_changes": {
|
"local_changes": {
|
||||||
"deleted": [],
|
"deleted": [],
|
||||||
|
"deleted_reftests": {},
|
||||||
"items": {},
|
"items": {},
|
||||||
"reftest_nodes": {}
|
"reftest_nodes": {}
|
||||||
},
|
},
|
||||||
|
@ -35587,6 +35710,66 @@
|
||||||
"url": "/compat/webkit-text-fill-color-property-001d.html"
|
"url": "/compat/webkit-text-fill-color-property-001d.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"compat/webkit-text-fill-color-property-002.html": [
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-002.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-002-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-002.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compat/webkit-text-fill-color-property-003.html": [
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-003.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-003-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-003.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compat/webkit-text-fill-color-property-004.html": [
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-004.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-004-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-004.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compat/webkit-text-fill-color-property-005.html": [
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-005.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-005-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-005.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compat/webkit-text-fill-color-property-006.html": [
|
||||||
|
{
|
||||||
|
"path": "compat/webkit-text-fill-color-property-006.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/compat/webkit-text-fill-color-property-006-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/compat/webkit-text-fill-color-property-006.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html": [
|
"custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html": [
|
||||||
{
|
{
|
||||||
"path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html",
|
"path": "custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html",
|
||||||
|
@ -41336,7 +41519,7 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"rev": "20fa4a3a71ab7a2f75b4febbe2e98aeeaf022c2b",
|
"rev": "0a518aaff73532a26e175789f7e75fa99593ac64",
|
||||||
"url_base": "/",
|
"url_base": "/",
|
||||||
"version": 3
|
"version": 3
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
type: testharness
|
type: testharness
|
||||||
[Element scroll maximum test]
|
[Element scroll maximum test]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[window-onerror-with-cross-frame-event-listeners-1.html]
|
||||||
|
type: testharness
|
||||||
|
bug: https://github.com/servo/servo/issues/3311
|
||||||
|
[The error event from an event listener should fire on that listener's global]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[window-onerror-with-cross-frame-event-listeners-2.html]
|
||||||
|
type: testharness
|
||||||
|
bug: https://github.com/servo/servo/issues/3311
|
||||||
|
[The error event from an event listener should fire on that listener's global]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[window-onerror-with-cross-frame-event-listeners-3.html]
|
||||||
|
type: testharness
|
||||||
|
bug: https://github.com/servo/servo/issues/3311
|
||||||
|
[The error event from an event listener should fire on that listener's global]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
[window-onerror-with-cross-frame-event-listeners-4.html]
|
||||||
|
type: testharness
|
||||||
|
bug: https://github.com/servo/servo/issues/3311
|
||||||
|
[The error event from an event listener should fire on that listener's global]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
3d4416e1b0ae758e68900f725979238cc0128f8b
|
9c172f49d08fe9019b0ba193ea4d75c6ddb95cda
|
5
tests/wpt/metadata/websockets/constructor/018.html.ini
Normal file
5
tests/wpt/metadata/websockets/constructor/018.html.ini
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[018.html]
|
||||||
|
type: testharness
|
||||||
|
[WebSockets: NULL char in url]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
},
|
},
|
||||||
"local_changes": {
|
"local_changes": {
|
||||||
"deleted": [],
|
"deleted": [],
|
||||||
|
"deleted_reftests": {},
|
||||||
"items": {
|
"items": {
|
||||||
"reftest": {
|
"reftest": {
|
||||||
"css/abs-overflow-stackingcontext.html": [
|
"css/abs-overflow-stackingcontext.html": [
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title> Event.defaultPrevented is reset after dipatchEvent() </title>
|
|
||||||
<script src="/resources/testharness.js"></script>
|
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id=log></div>
|
|
||||||
|
|
||||||
<input id="target" type="hidden" value=""/>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var EVENT = "foo";
|
|
||||||
var TARGET = document.getElementById("target");
|
|
||||||
var PreState;
|
|
||||||
var PosState;
|
|
||||||
|
|
||||||
var description = "Test Description: " +
|
|
||||||
"As the final step of the event dispatch, the implementation must reset the event " +
|
|
||||||
"object's default-action-prevention state. ";
|
|
||||||
|
|
||||||
test(function()
|
|
||||||
{
|
|
||||||
var evt = document.createEvent("Event");
|
|
||||||
evt.initEvent(EVENT, true, true);
|
|
||||||
|
|
||||||
TARGET.addEventListener(EVENT, TestEvent, true);
|
|
||||||
TARGET.dispatchEvent(evt);
|
|
||||||
|
|
||||||
PosState = evt.defaultPrevented;
|
|
||||||
|
|
||||||
assert_array_equals([evt.target, PreState, PosState], [TARGET, true, false]);
|
|
||||||
|
|
||||||
}, description);
|
|
||||||
|
|
||||||
function TestEvent(evt)
|
|
||||||
{
|
|
||||||
evt.preventDefault();
|
|
||||||
PreState = evt.defaultPrevented;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title> Event.defaultPrevented is reset after dipatchEvent() </title>
|
|
||||||
<script src="/resources/testharness.js"></script>
|
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id=log></div>
|
|
||||||
|
|
||||||
<input id="target" type="hidden" value=""/>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
var EVENT = "foo";
|
|
||||||
var TARGET = document.getElementById("target");
|
|
||||||
var PreState;
|
|
||||||
var PosState;
|
|
||||||
|
|
||||||
var description = "Test Description: " +
|
|
||||||
"As the final step of the event dispatch, the implementation must reset the event " +
|
|
||||||
"object's default-action-prevention state. ";
|
|
||||||
|
|
||||||
test(function()
|
|
||||||
{
|
|
||||||
var evt = document.createEvent("Event");
|
|
||||||
evt.initEvent(EVENT, true, true);
|
|
||||||
|
|
||||||
TARGET.addEventListener(EVENT, TestEvent, true);
|
|
||||||
TARGET.dispatchEvent(evt);
|
|
||||||
|
|
||||||
PosState = evt.defaultPrevented;
|
|
||||||
|
|
||||||
assert_array_equals([evt.target, PreState, PosState], [TARGET, true, false]);
|
|
||||||
|
|
||||||
}, description);
|
|
||||||
|
|
||||||
function TestEvent(evt)
|
|
||||||
{
|
|
||||||
evt.preventDefault();
|
|
||||||
PreState = evt.defaultPrevented;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -23,22 +23,28 @@ test(function() {
|
||||||
assert_equals(String(blob), '[object Blob]');
|
assert_equals(String(blob), '[object Blob]');
|
||||||
assert_equals(blob.size, 0);
|
assert_equals(blob.size, 0);
|
||||||
assert_equals(blob.type, "");
|
assert_equals(blob.type, "");
|
||||||
}, "no-argument Blob constructor");
|
}, "Blob constructor with no arguments");
|
||||||
test(function() {
|
test(function() {
|
||||||
assert_throws(new TypeError(), function() { var blob = Blob(); });
|
assert_throws(new TypeError(), function() { var blob = Blob(); });
|
||||||
}, "no-argument Blob constructor without 'new'");
|
}, "Blob constructor with no arguments, without 'new'");
|
||||||
test(function() {
|
test(function() {
|
||||||
var blob = new Blob;
|
var blob = new Blob;
|
||||||
assert_true(blob instanceof Blob);
|
assert_true(blob instanceof Blob);
|
||||||
assert_equals(blob.size, 0);
|
assert_equals(blob.size, 0);
|
||||||
assert_equals(blob.type, "");
|
assert_equals(blob.type, "");
|
||||||
}, "no-argument Blob constructor without brackets");
|
}, "Blob constructor without brackets");
|
||||||
|
test(function() {
|
||||||
|
var blob = new Blob(undefined);
|
||||||
|
assert_true(blob instanceof Blob);
|
||||||
|
assert_equals(String(blob), '[object Blob]');
|
||||||
|
assert_equals(blob.size, 0);
|
||||||
|
assert_equals(blob.type, "");
|
||||||
|
}, "Blob constructor with undefined as first argument");
|
||||||
|
|
||||||
// blobParts argument (WebIDL).
|
// blobParts argument (WebIDL).
|
||||||
test(function() {
|
test(function() {
|
||||||
var args = [
|
var args = [
|
||||||
null,
|
null,
|
||||||
undefined,
|
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color on selected text reference</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<style>
|
||||||
|
p {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body onload="onload()">
|
||||||
|
<p>Pass if color of <span id="selectMe">selected text</span> is green or inverted (depending on the platform convention), but not red</p>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function onload() {
|
||||||
|
var elt = document.getElementById("selectMe");
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNode(elt);
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
document.documentElement.classList.remove('reftest-wait');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color should take effect while rendering selected text</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
|
||||||
|
<meta name="assert" content="The color of selected text should be green">
|
||||||
|
<link rel="match" href="webkit-text-fill-color-property-002-ref.html">
|
||||||
|
<style>
|
||||||
|
p {
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body onload="onload()">
|
||||||
|
<p>Pass if color of <span id="selectMe">selected text</span> is green or inverted (depending on the platform convention), but not red</p>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function onload() {
|
||||||
|
var elt = document.getElementById("selectMe");
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNode(elt);
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
document.documentElement.classList.remove('reftest-wait');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color on ::-moz-selection selected text reference</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<style>
|
||||||
|
::-moz-selection {
|
||||||
|
color: green; background: skyblue;
|
||||||
|
}
|
||||||
|
::selection {
|
||||||
|
color: green; background: skyblue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body onload="onload()">
|
||||||
|
<p>Pass if color of <span id="selectMe">selected text</span> is green!!!</p>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function onload() {
|
||||||
|
var elt = document.getElementById("selectMe");
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNode(elt);
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
document.documentElement.classList.remove('reftest-wait');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color should take effect while rendering ::-moz-selection selected text</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
|
||||||
|
<meta name="assert" content="The color of selected text should be green">
|
||||||
|
<link rel="match" href="webkit-text-fill-color-property-003-ref.html">
|
||||||
|
<style>
|
||||||
|
::-moz-selection {
|
||||||
|
background: skyblue;
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
::selection {
|
||||||
|
background: skyblue;
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body onload="onload()">
|
||||||
|
<p>Pass if color of <span id="selectMe">selected text</span> is green!!!</p>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function onload() {
|
||||||
|
var elt = document.getElementById("selectMe");
|
||||||
|
var range = document.createRange();
|
||||||
|
range.selectNode(elt);
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
document.documentElement.classList.remove('reftest-wait');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color on MathML reference</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<style>
|
||||||
|
math {
|
||||||
|
font-size: 50px;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<p>Pass if color of operators and operands are all green!!!</p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mrow>
|
||||||
|
<msup>
|
||||||
|
<mi>a</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
<mo>+</mo>
|
||||||
|
<msup>
|
||||||
|
<mi>b</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
<mo>=</mo>
|
||||||
|
<msup>
|
||||||
|
<mi>c</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</body>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color should take effect while rendering MathML</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
|
||||||
|
<meta name="assert" content="The color of MathML should be green">
|
||||||
|
<link rel="match" href="webkit-text-fill-color-property-004-ref.html">
|
||||||
|
<style>
|
||||||
|
math {
|
||||||
|
font-size: 50px;
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<p>Pass if color of operators and operands are all green!!!</p>
|
||||||
|
<math>
|
||||||
|
<mrow>
|
||||||
|
<mrow>
|
||||||
|
<msup>
|
||||||
|
<mi>a</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
<mo>+</mo>
|
||||||
|
<msup>
|
||||||
|
<mi>b</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
<mo>=</mo>
|
||||||
|
<msup>
|
||||||
|
<mi>c</mi>
|
||||||
|
<mn>2</mn>
|
||||||
|
</msup>
|
||||||
|
</mrow>
|
||||||
|
</math>
|
||||||
|
</body>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color on text-decoration underline reference</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<style type="text/css">
|
||||||
|
p {
|
||||||
|
font-size: 50px;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div><p>Pass if text underline is green!!!</p></div>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color should take effect while rendering text-decoration underline</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
|
||||||
|
<meta name="assert" content="The color of text-decoration underline should be green">
|
||||||
|
<link rel="match" href="webkit-text-fill-color-property-005-ref.html">
|
||||||
|
<style type="text/css">
|
||||||
|
p {
|
||||||
|
font-size: 50px;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div><p>Pass if text underline is green!!!</p></div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color on text-overflow ellipsis reference</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
font-size: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 150px;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-family: Ahem;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a <strong>green ellipsis</strong> after "TestChecks".</p>
|
||||||
|
<div>
|
||||||
|
<span>TestChecksThatTextColorAndEllipsisColorShouldBeTheSame</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>webkit-text-fill-color should take effect while rendering text-overflow ellipsis</title>
|
||||||
|
<link rel="author" title="Jeremy Chen" href="jeremychen@mozilla.com">
|
||||||
|
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||||
|
<link rel="help" href="https://compat.spec.whatwg.org/#the-webkit-text-fill-color">
|
||||||
|
<meta name="assert" content="The color of text-overflow ellipsis should be green">
|
||||||
|
<link rel="match" href="webkit-text-fill-color-property-006-ref.html">
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
font-size: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 150px;
|
||||||
|
color: red;
|
||||||
|
-webkit-text-fill-color: green;
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
font-family: Ahem;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a <strong>green ellipsis</strong> after "TestChecks".</p>
|
||||||
|
<div>
|
||||||
|
<span>TestChecksThatTextColorAndEllipsisColorShouldBeTheSame</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
|
@ -32,7 +32,7 @@ form-action 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
<input type="text" name="fieldname" value="fieldvalue">
|
<input type="text" name="fieldname" value="fieldvalue">
|
||||||
<input type="submit" id="submit" value="submit">
|
<input type="submit" id="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
<p>Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.</p>
|
<p>Tests that allowed form actions work correctly.</p>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -31,7 +31,7 @@ form-action 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
<input type="text" name="fieldname" value="fieldvalue">
|
<input type="text" name="fieldname" value="fieldvalue">
|
||||||
<input type="submit" id="submit" value="submit">
|
<input type="submit" id="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
<p>Tests that blocking form actions works correctly. If this test passes, a CSP violation will be generated, and will not see a page indicating a form was POSTed.</p>
|
<p>Tests that blocking form actions works correctly.</p>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'none'"></script>
|
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'none'"></script>
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ form-action 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
<input type="text" name="fieldname" value="fieldvalue">
|
<input type="text" name="fieldname" value="fieldvalue">
|
||||||
<input type="submit" id="submit" value="submit">
|
<input type="submit" id="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
<p>Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.</p>
|
<p>Tests that allowed form actions work correctly
|
||||||
|
with GET and a redirect.</p>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -33,7 +33,8 @@ form-action 'none'; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
<input type="text" name="fieldname" value="fieldvalue">
|
<input type="text" name="fieldname" value="fieldvalue">
|
||||||
<input type="submit" id="submit" value="submit">
|
<input type="submit" id="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
<p>Tests that allowed form actions work correctly. If this test passes, you will see a page indicating a form was POSTed.</p>
|
<p>Tests that disallowed form actions are blocked
|
||||||
|
with GET and redirects.</p>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'none'
|
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'none'
|
||||||
"></script>
|
"></script>
|
||||||
|
|
|
@ -33,7 +33,7 @@ form-action 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
<input type="text" name="fieldname" value="fieldvalue">
|
<input type="text" name="fieldname" value="fieldvalue">
|
||||||
<input type="submit" id="submit" value="submit">
|
<input type="submit" id="submit" value="submit">
|
||||||
</form>
|
</form>
|
||||||
<p>Tests that blocking form redirect works correctly. If this test passes, a CSP violation will be generated, and will not see a page indicating a form was POSTed.</p>
|
<p>Tests that blocking a POST form with a redirect works correctly. If this test passes, a CSP violation will be generated.</p>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'self'"></script>
|
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=form-action%20'self'"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -14,14 +14,14 @@ script-src 'self' 'unsafe-inline' 'none'; connect-src 'self';
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
|
<meta http-equiv="Content-Security-Policy" content="script-src 'self'">
|
||||||
<p>This test checks that Content Security Policy delivered via a meta element is not enforced if the element is outside the document's head.</p>
|
<p>This test checks that Content Security Policy delivered via a meta element is not enforced if the element is outside the document's head.</p>
|
||||||
<script>
|
<script>
|
||||||
alert_assert("PASS (1/1)");
|
var aa = "PASS (1/1)";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<script src="metaHelper.js"></script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
<script src="../support/checkReport.sub.js?reportExists=false"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
if (typeof aa != 'undefined') {
|
||||||
|
alert_assert(aa);
|
||||||
|
} else {
|
||||||
|
alert_assert("Failed - allowed inline script blocked by meta policy outside head.");
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
<title>plugintypes-notype-data</title>
|
<title>plugintypes-notype-data</title>
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src='../support/logTest.sub.js?logs=["PASS"]'></script>
|
<script src='../support/logTest.sub.js?logs=["PASS: object tag onerror handler fired"]'></script>
|
||||||
<script src="../support/alertAssert.sub.js?alerts=[]"></script>
|
<script src="../support/alertAssert.sub.js?alerts=[]"></script>
|
||||||
<!-- enforcing policy:
|
<!-- enforcing policy:
|
||||||
plugin-types application/x-invalid-type; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
plugin-types application/x-invalid-type; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
|
@ -15,7 +15,7 @@ plugin-types application/x-invalid-type; script-src 'self' 'unsafe-inline'; conn
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
Given a `plugin-types` directive, plugins have to declare a type explicitly. No declared type, no load. This test passes if there's a CSP report and "FAIL!" isn't logged.
|
Given a `plugin-types` directive, plugins have to declare a type explicitly. No declared type, no load. This test passes if there's a CSP report and "FAIL!" isn't logged.
|
||||||
<object data="data:application/x-webkit-test-netscape" onload="log('FAIL');" onerror="log('PASS');"></object>
|
<object data="data:application/x-webkit-test-netscape" onload="log('FAIL');" onerror="log('PASS: object tag onerror handler fired');"></object>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=plugin-types+application/x-invalid-type"></script>
|
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=plugin-types+application/x-invalid-type"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
</script>
|
|
||||||
<!-- enforcing policy:
|
<!-- enforcing policy:
|
||||||
script-src 'self' 'nonce-nonceynonce' 'sha256-dWTP4Di8KBjaiXvQ5mRquI9OoBSo921ahYxLfYSiuT8='; connect-src 'self';
|
script-src 'self' 'nonce-nonceynonce' 'sha256-dWTP4Di8KBjaiXvQ5mRquI9OoBSo921ahYxLfYSiuT8='; connect-src 'self';
|
||||||
-->
|
-->
|
||||||
|
@ -34,12 +33,9 @@ script-src 'self' 'nonce-nonceynonce' 'sha256-dWTP4Di8KBjaiXvQ5mRquI9OoBSo921ahY
|
||||||
var scriptContent2 = "window.finish('" + nonMatchingContent + "');";
|
var scriptContent2 = "window.finish('" + nonMatchingContent + "');";
|
||||||
|
|
||||||
var script1 = document.createElement('script');
|
var script1 = document.createElement('script');
|
||||||
script1.innerHTML = scriptContent1;
|
|
||||||
var script2 = document.createElement('script');
|
var script2 = document.createElement('script');
|
||||||
script2.innerHTML = scriptContent2;
|
|
||||||
|
|
||||||
script1.test = async_test("Inline script with hash in CSP");
|
script1.test = async_test("Only matching content runs even with NFC normalization.");
|
||||||
script2.test = async_test("Inline script without hash in CSP");
|
|
||||||
|
|
||||||
var failure = function() {
|
var failure = function() {
|
||||||
assert_unreached();
|
assert_unreached();
|
||||||
|
@ -51,16 +47,18 @@ script-src 'self' 'nonce-nonceynonce' 'sha256-dWTP4Di8KBjaiXvQ5mRquI9OoBSo921ahY
|
||||||
script1.test.done();
|
script1.test.done();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
assert_unreached();
|
script1.test.step(function() {
|
||||||
|
assert_unreached("nonMatchingContent script ran");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script1.onerror = failure;
|
script1.onerror = failure;
|
||||||
script2.onerror = script2.test.step_func(function() {
|
|
||||||
script2.test.done();
|
|
||||||
});
|
|
||||||
document.body.appendChild(script1);
|
|
||||||
document.body.appendChild(script2);
|
document.body.appendChild(script2);
|
||||||
|
script2.textContent = scriptContent2;
|
||||||
|
document.body.appendChild(script1);
|
||||||
|
script1.textContent = scriptContent1;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -6,49 +6,16 @@
|
||||||
<title>scriptnonce-basic-blocked</title>
|
<title>scriptnonce-basic-blocked</title>
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script nonce='noncynonce'>
|
<script src='../support/alertAssert.sub.js?alerts=["PASS (closely-quoted nonce)","PASS (nonce w/whitespace)"]'></script>
|
||||||
function log(msg) {
|
|
||||||
test(function() {
|
|
||||||
assert_unreached(msg)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<script nonce='noncynonce'>
|
|
||||||
var t_alert = async_test('Expecting alerts: ["PASS (1/2)","PASS (2/2)"]');
|
|
||||||
var expected_alerts = ["PASS (1/2)", "PASS (2/2)"];
|
|
||||||
|
|
||||||
function alert_assert(msg) {
|
|
||||||
t_alert.step(function() {
|
|
||||||
if (msg.match(/^FAIL/i)) {
|
|
||||||
assert_unreached(msg);
|
|
||||||
t_alert.done();
|
|
||||||
}
|
|
||||||
for (var i = 0; i < expected_alerts.length; i++) {
|
|
||||||
if (expected_alerts[i] == msg) {
|
|
||||||
assert_true(expected_alerts[i] == msg);
|
|
||||||
expected_alerts.splice(i, 1);
|
|
||||||
if (expected_alerts.length == 0) {
|
|
||||||
t_alert.done();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_unreached('unexpected alert: ' + msg);
|
|
||||||
t_log.done();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<!-- enforcing policy:
|
<!-- enforcing policy:
|
||||||
script-src 'self' 'unsafe-inline' 'nonce-noncynonce'; connect-src 'self';
|
script-src 'self' 'unsafe-inline' 'nonce-noncynonce'; connect-src 'self';
|
||||||
-->
|
-->
|
||||||
<script nonce="noncynonce">
|
<script nonce="noncynonce">
|
||||||
alert_assert('PASS (1/2)');
|
alert_assert('PASS (closely-quoted nonce)');
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script nonce=" noncynonce ">
|
<script nonce=" noncynonce ">
|
||||||
alert_assert('PASS (2/2)');
|
alert_assert('PASS (nonce w/whitespace)');
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script nonce="noncynonce noncynonce">
|
<script nonce="noncynonce noncynonce">
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<!-- enforcing policy:
|
<!-- enforcing policy:
|
||||||
style-src 'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw=' 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw=' 'sha384-bSVm1i3sjPBRM4TwZtYTDjk9JxZMExYHWbFmP1SxDhJH4ue0Wu9OPOkY5hcqRcSt' 'sha512-440MmBLtj9Kp5Bqloogn9BqGDylY8vFsv5/zXL1zH2fJVssCoskRig4gyM+9KqwvCSapSz5CVoUGHQcxv43UQg=='; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
style-src 'sha256-pAKi9r4/WB7fHydbE3F3t8i8602ij2JN8zHJpL2T5BM=' 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw=' 'sha384-bSVm1i3sjPBRM4TwZtYTDjk9JxZMExYHWbFmP1SxDhJH4ue0Wu9OPOkY5hcqRcSt' 'sha512-440MmBLtj9Kp5Bqloogn9BqGDylY8vFsv5/zXL1zH2fJVssCoskRig4gyM+9KqwvCSapSz5CVoUGHQcxv43UQg=='; script-src 'self' 'unsafe-inline'; connect-src 'self';
|
||||||
-->
|
-->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,4 @@ Cache-Control: no-store, no-cache, must-revalidate
|
||||||
Cache-Control: post-check=0, pre-check=0, false
|
Cache-Control: post-check=0, pre-check=0, false
|
||||||
Pragma: no-cache
|
Pragma: no-cache
|
||||||
Set-Cookie: stylehash-allowed={{$id:uuid()}}; Path=/content-security-policy/blink-contrib-2
|
Set-Cookie: stylehash-allowed={{$id:uuid()}}; Path=/content-security-policy/blink-contrib-2
|
||||||
Content-Security-Policy: style-src 'self' 'sha1-eYyYGmKWdhpUewohaXk9o8IaLSw=' 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw=' 'sha384-bSVm1i3sjPBRM4TwZtYTDjk9JxZMExYHWbFmP1SxDhJH4ue0Wu9OPOkY5hcqRcSt' 'sha512-440MmBLtj9Kp5Bqloogn9BqGDylY8vFsv5/zXL1zH2fJVssCoskRig4gyM+9KqwvCSapSz5CVoUGHQcxv43UQg=='; script-src 'self' 'unsafe-inline'; connect-src 'self'; report-uri /content-security-policy/support/report.py?op=put&reportID={{$id}}
|
Content-Security-Policy: style-src 'self' 'sha256-pAKi9r4/WB7fHydbE3F3t8i8602ij2JN8zHJpL2T5BM=' 'sha256-hndjYvzUzy2Ykuad81Cwsl1FOXX/qYs/aDVyUyNZwBw=' 'sha384-bSVm1i3sjPBRM4TwZtYTDjk9JxZMExYHWbFmP1SxDhJH4ue0Wu9OPOkY5hcqRcSt' 'sha512-440MmBLtj9Kp5Bqloogn9BqGDylY8vFsv5/zXL1zH2fJVssCoskRig4gyM+9KqwvCSapSz5CVoUGHQcxv43UQg=='; script-src 'self' 'unsafe-inline'; connect-src 'self'; report-uri /content-security-policy/support/report.py?op=put&reportID={{$id}}
|
||||||
|
|
|
@ -15,16 +15,27 @@ connect-src 'self' http://{{host}}:{{ports[http][0]}}; script-src 'self' 'unsafe
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
try {
|
if (typeof navigator.sendBeacon != 'function') {
|
||||||
var es = navigator.sendBeacon("http://{{host}}:{{ports[http][0]}}/cors/resources/status.py");
|
t_log.set_status(t_log.NOTRUN, "No navigator.sendBeacon, cannot run test.");
|
||||||
log("Pass");
|
t_log.phase = t_log.phases.HAS_RESULT;
|
||||||
} catch (e) {
|
t_log.done();
|
||||||
log("Fail");
|
} else {
|
||||||
}
|
try {
|
||||||
|
var es = navigator.sendBeacon("http://{{host}}:{{ports[http][0]}}/cors/resources/status.py");
|
||||||
|
log("Pass");
|
||||||
|
} catch (e) {
|
||||||
|
log("Fail");
|
||||||
|
}
|
||||||
|
var report = document.createElement("script");
|
||||||
|
report.src = "../support/checkReport.sub.js?reportExists=false";
|
||||||
|
report.async = true;
|
||||||
|
report.defer = true;
|
||||||
|
document.body.appendChild(report);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -15,16 +15,26 @@ connect-src 'self' http://{{host}}:{{ports[http][0]}}; script-src 'self' 'unsafe
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
try {
|
if (typeof navigator.sendBeacon != 'function') {
|
||||||
var es = navigator.sendBeacon("http://www1.{{host}}:{{ports[http][0]}}/security/contentSecurityPolicy/echo-report.php");
|
t_log.set_status(t_log.NOTRUN, "No navigator.sendBeacon, cannot run test.");
|
||||||
log("Fail");
|
t_log.phase = t_log.phases.HAS_RESULT;
|
||||||
} catch (e) {
|
t_log.done();
|
||||||
log("Pass");
|
} else {
|
||||||
}
|
try {
|
||||||
|
var es = navigator.sendBeacon("http://www1.{{host}}:{{ports[http][0]}}/security/contentSecurityPolicy/echo-report.php");
|
||||||
|
log("Fail");
|
||||||
|
} catch (e) {
|
||||||
|
log("Pass");
|
||||||
|
}
|
||||||
|
var report = document.createElement("script");
|
||||||
|
report.src = "../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=connect-src%20'self'";
|
||||||
|
report.async = true;
|
||||||
|
report.defer = true;
|
||||||
|
document.body.appendChild(report);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=connect-src%20'self'"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -18,13 +18,24 @@ connect-src 'self'; script-src 'self' 'unsafe-inline';
|
||||||
<p>The beacon should not follow the redirect to http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png and send a CSP violation report.</p>
|
<p>The beacon should not follow the redirect to http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png and send a CSP violation report.</p>
|
||||||
<p>Verify that a CSP connect-src directive blocks redirects.</p>
|
<p>Verify that a CSP connect-src directive blocks redirects.</p>
|
||||||
<script>
|
<script>
|
||||||
navigator.sendBeacon(
|
if (typeof navigator.sendBeacon != 'function') {
|
||||||
"/common/redirect.py?location=http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png",
|
var t = async_test();
|
||||||
"ping");
|
t.set_status(t.NOTRUN, "No navigator.sendBeacon, cannot run test.");
|
||||||
|
t.phase = t.phases.HAS_RESULT;
|
||||||
|
t.done();
|
||||||
|
} else {
|
||||||
|
navigator.sendBeacon(
|
||||||
|
"/common/redirect.py?location=http://www1.{{host}}:{{ports[http][0]}}/content-security-policy/support/fail.png",
|
||||||
|
"ping");
|
||||||
|
var report = document.createElement("script");
|
||||||
|
report.src = "../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=connect-src%20'self'";
|
||||||
|
report.async = true;
|
||||||
|
report.defer = true;
|
||||||
|
document.body.appendChild(report);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=true&reportField=violated-directive&reportValue=connect-src%20'self'"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,5 +2,5 @@ try {
|
||||||
importScripts("/content-security-policy/blink-contrib/resources/post-message.js");
|
importScripts("/content-security-policy/blink-contrib/resources/post-message.js");
|
||||||
postMessage("importScripts allowed");
|
postMessage("importScripts allowed");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
postMessage("importScripts blocked: " + e);
|
postMessage("importScripts blocked");
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@ connect-src 'self' http://{{host}}:{{ports[http][0]}}; script-src 'self' 'unsafe
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
|
if(typeof SharedWorker != 'function') {
|
||||||
|
t_alert.set_status(t_alert.NOTRUN, "No SharedWorker, cannot run test.");
|
||||||
|
t_alert.phase = t_alert.phases.HAS_RESULT;
|
||||||
|
t_alert.done();
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
var worker = new SharedWorker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/shared-worker-make-xhr-allowed.sub.js');
|
var worker = new SharedWorker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/shared-worker-make-xhr-allowed.sub.js');
|
||||||
worker.port.onmessage = function(event) {
|
worker.port.onmessage = function(event) {
|
||||||
|
@ -24,10 +29,15 @@ connect-src 'self' http://{{host}}:{{ports[http][0]}}; script-src 'self' 'unsafe
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert_assert(e);
|
alert_assert(e);
|
||||||
}
|
}
|
||||||
|
var report = document.createElement("script");
|
||||||
|
report.src = "../support/checkReport.sub.js?reportExists=false";
|
||||||
|
report.async = true;
|
||||||
|
report.defer = true;
|
||||||
|
document.body.appendChild(report);
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -22,6 +22,11 @@ connect-src *; script-src 'self' 'unsafe-inline';
|
||||||
should be sent since the worker's policy doesn't specify
|
should be sent since the worker's policy doesn't specify
|
||||||
a report-uri.</p>
|
a report-uri.</p>
|
||||||
<script>
|
<script>
|
||||||
|
if(typeof SharedWorker != 'function') {
|
||||||
|
t_alert.set_status(t_alert.NOTRUN, "No SharedWorker, cannot run test.");
|
||||||
|
t_alert.phase = t_alert.phases.HAS_RESULT;
|
||||||
|
t_alert.done();
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
var worker = new SharedWorker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/shared-worker-make-xhr-blocked.sub.js');
|
var worker = new SharedWorker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/shared-worker-make-xhr-blocked.sub.js');
|
||||||
worker.port.onmessage = function(event) {
|
worker.port.onmessage = function(event) {
|
||||||
|
@ -30,10 +35,16 @@ connect-src *; script-src 'self' 'unsafe-inline';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert_assert(e);
|
alert_assert(e);
|
||||||
}
|
}
|
||||||
|
var report = document.createElement("script");
|
||||||
|
report.src = "../support/checkReport.sub.js?reportExists=false";
|
||||||
|
report.async = true;
|
||||||
|
report.defer = true;
|
||||||
|
document.body.appendChild(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -23,7 +23,7 @@ script-src 'self' 'unsafe-inline' 'unsafe-eval' 'unsafe-inline' 127.0.0.1:8000;
|
||||||
worker.onmessage = function(event) {
|
worker.onmessage = function(event) {
|
||||||
result = event.data;
|
result = event.data;
|
||||||
test(function() {
|
test(function() {
|
||||||
assert_equals(result, 'importScripts blocked: NetworkError: Failed to execute \'importScripts\' on \'WorkerGlobalScope\': The script at \'http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/post-message.js\' failed to load.')
|
assert_equals(result, 'importScripts blocked')
|
||||||
});
|
});
|
||||||
log("TEST COMPLETE");
|
log("TEST COMPLETE");
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,6 +17,10 @@ child-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-inline'; connect-src
|
||||||
<script>
|
<script>
|
||||||
try {
|
try {
|
||||||
var foo = new Worker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/post-message.js');
|
var foo = new Worker('http://{{host}}:{{ports[http][0]}}/content-security-policy/blink-contrib/resources/post-message.js');
|
||||||
|
foo.onerror = function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
alert_assert("PASS");
|
||||||
|
}
|
||||||
foo.onmessage = function(event) {
|
foo.onmessage = function(event) {
|
||||||
alert_assert("FAIL");
|
alert_assert("FAIL");
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,10 +52,17 @@
|
||||||
source_test.step(function() {
|
source_test.step(function() {
|
||||||
source_test.set_status(source_test.FAIL);
|
source_test.set_status(source_test.FAIL);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
if(source_test.phase != source_test.phases.COMPLETE) {
|
||||||
|
source_test.step( function () { assert_unreached("Onerror event never fired for track element."); });
|
||||||
|
source_test.done();
|
||||||
|
}
|
||||||
|
}, 2 * 1000);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=media-src%20%27self%27">
|
<script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=media-src%20%27self%27">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -55,8 +55,8 @@
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<video id="videoObject2" width="320" height="240" controls
|
<video id="videoObject2" width="320" height="240" controls
|
||||||
onerror="media_error_handler(src_test)"
|
onerror="media_error_handler(src_redir_test)"
|
||||||
onloadeddata="media_loaded(src_test)"
|
onloadeddata="media_loaded(src_redir_test)"
|
||||||
src="/common/redirect.py?location=http://www2.{{host}}:{{ports[http][0]}}/media/white.mp4">
|
src="/common/redirect.py?location=http://www2.{{host}}:{{ports[http][0]}}/media/white.mp4">
|
||||||
|
|
||||||
<script async defer src="../support/checkReport.sub.js?reportExists=false">
|
<script async defer src="../support/checkReport.sub.js?reportExists=false">
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
// note, this template substitution is XSS, but no way to avoid it in this framework
|
// note, this template substitution is XSS, but no way to avoid it in this framework
|
||||||
var expected_alerts = {{GET[alerts]}};
|
var expected_alerts = {{GET[alerts]}};
|
||||||
|
var timeout= "{{GET[timeout]}}";
|
||||||
|
if (timeout == "") {
|
||||||
|
timeout = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if(expected_alerts.length == 0) {
|
if(expected_alerts.length == 0) {
|
||||||
function alert_assert(msg) {
|
function alert_assert(msg) {
|
||||||
|
@ -7,7 +11,13 @@ if(expected_alerts.length == 0) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var t_alert = async_test('Expecting alerts: {{GET[alerts]}}');
|
var t_alert = async_test('Expecting alerts: {{GET[alerts]}}');
|
||||||
function alert_assert(msg) {
|
setTimeout(function() {
|
||||||
|
if(t_alert.phase != t_alert.phases.COMPLETE) {
|
||||||
|
t_alert.step(function() { assert_unreached('Alert timeout, expected alerts ' + expected_alerts + ' not fired.') });
|
||||||
|
t_alert.done();
|
||||||
|
}
|
||||||
|
}, timeout * 100);
|
||||||
|
var alert_assert = function (msg) {
|
||||||
t_alert.step(function () {
|
t_alert.step(function () {
|
||||||
if(msg && msg instanceof Error) {
|
if(msg && msg instanceof Error) {
|
||||||
msg = msg.message;
|
msg = msg.message;
|
||||||
|
@ -29,5 +39,5 @@ if(expected_alerts.length == 0) {
|
||||||
assert_unreached('unexpected alert: ' + msg);
|
assert_unreached('unexpected alert: ' + msg);
|
||||||
t_log.done();
|
t_log.done();
|
||||||
});
|
});
|
||||||
}
|
}.bind(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
// note, this template substitution is XSS, but no way to avoid it in this framework
|
// note, this template substitution is XSS, but no way to avoid it in this framework
|
||||||
var expected_logs = {{GET[logs]}};
|
var expected_logs = {{GET[logs]}};
|
||||||
|
var timeout = "{{GET[timeout]}}";
|
||||||
|
if (timeout == "") {
|
||||||
|
timeout = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (expected_logs.length == 0) {
|
if (expected_logs.length == 0) {
|
||||||
function log_assert(msg) {
|
function log_assert(msg) {
|
||||||
|
@ -7,6 +11,12 @@ if (expected_logs.length == 0) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var t_log = async_test('Expecting logs: {{GET[logs]}}');
|
var t_log = async_test('Expecting logs: {{GET[logs]}}');
|
||||||
|
setTimeout(function() {
|
||||||
|
if(t_log.phase != t_log.phases.COMPLETE){
|
||||||
|
t_log.step(function () { assert_unreached('Logging timeout, expected logs ' + expected_logs + ' not sent.') });
|
||||||
|
t_log.done();
|
||||||
|
}
|
||||||
|
}, timeout * 1000);
|
||||||
function log(msg) {
|
function log(msg) {
|
||||||
//cons/**/ole.log(msg);
|
//cons/**/ole.log(msg);
|
||||||
t_log.step(function () {
|
t_log.step(function () {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Event.defaultPrevented is not reset after dipatchEvent()</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=log></div>
|
||||||
|
<input id="target" type="hidden" value=""/>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var EVENT = "foo";
|
||||||
|
var TARGET = document.getElementById("target");
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(EVENT, true, true);
|
||||||
|
|
||||||
|
TARGET.addEventListener(EVENT, this.step_func(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
assert_true(e.defaultPrevented, "during dispatch");
|
||||||
|
}), true);
|
||||||
|
TARGET.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_true(evt.defaultPrevented, "after dispatch");
|
||||||
|
assert_equals(evt.target, TARGET);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,3 +1,4 @@
|
||||||
|
@ayg
|
||||||
@Ms2ger
|
@Ms2ger
|
||||||
@foolip
|
@foolip
|
||||||
@gsnedders
|
@gsnedders
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>HTML Test: The embed element represents a document</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<meta name="assert" content="Check if the embed element is ignored when used inside a media element">
|
||||||
|
<script type="application/javascript">
|
||||||
|
window.childLoaded = false;
|
||||||
|
async_test(function() {
|
||||||
|
addEventListener("load", this.step_func_done(function() {
|
||||||
|
assert_false(window.childLoaded);
|
||||||
|
}));
|
||||||
|
}, "Test embed being ignored inside media element");
|
||||||
|
</script>
|
||||||
|
<body>
|
||||||
|
<video>
|
||||||
|
<embed type="text/html" src="embed-iframe.html" />
|
||||||
|
</video>
|
||||||
|
<audio>
|
||||||
|
<embed type="text/html" src="embed-iframe.html" />
|
||||||
|
</audio>
|
||||||
|
</body>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>
|
||||||
|
When a listener from window A is added to an event target in window B via the
|
||||||
|
addEventListener function from window B, errors in that listener should be
|
||||||
|
reported to window A.
|
||||||
|
</title>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<iframe></iframe>
|
||||||
|
<iframe></iframe>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var f = new frames[0].Function("thereIsNoSuchCallable()");
|
||||||
|
frames[1].document.addEventListener("myevent", f);
|
||||||
|
var frame0ErrorFired = false;
|
||||||
|
var frame1ErrorFired = false;
|
||||||
|
var ourErrorFired = false;
|
||||||
|
frames[0].addEventListener("error", function() {
|
||||||
|
frame0ErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].addEventListener("error", function() {
|
||||||
|
frame1ErrorFired = true;
|
||||||
|
});
|
||||||
|
addEventListener("error", function() {
|
||||||
|
ourErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].document.dispatchEvent(new Event("myevent"));
|
||||||
|
assert_true(frame0ErrorFired);
|
||||||
|
assert_false(frame1ErrorFired);
|
||||||
|
assert_false(ourErrorFired);
|
||||||
|
}, "The error event from an event listener should fire on that listener's global");
|
||||||
|
</script>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>
|
||||||
|
When a listener from window A is added to an event target in window B via the
|
||||||
|
addEventListener function from window A, errors in that listener should be
|
||||||
|
reported to window A.
|
||||||
|
</title>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<iframe></iframe>
|
||||||
|
<iframe></iframe>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var f = new frames[0].Function("thereIsNoSuchCallable()");
|
||||||
|
frames[0].document.addEventListener.call(frames[1].document, "myevent", f);
|
||||||
|
var frame0ErrorFired = false;
|
||||||
|
var frame1ErrorFired = false;
|
||||||
|
var ourErrorFired = false;
|
||||||
|
frames[0].addEventListener("error", function() {
|
||||||
|
frame0ErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].addEventListener("error", function() {
|
||||||
|
frame1ErrorFired = true;
|
||||||
|
});
|
||||||
|
addEventListener("error", function() {
|
||||||
|
ourErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].document.dispatchEvent(new Event("myevent"));
|
||||||
|
assert_true(frame0ErrorFired);
|
||||||
|
assert_false(frame1ErrorFired);
|
||||||
|
assert_false(ourErrorFired);
|
||||||
|
}, "The error event from an event listener should fire on that listener's global");
|
||||||
|
</script>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>
|
||||||
|
When a listener from window A is added to an event target in window A via the
|
||||||
|
addEventListener function from window A, errors in that listener should be
|
||||||
|
reported to window A.
|
||||||
|
</title>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<iframe></iframe>
|
||||||
|
<iframe></iframe>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var f = new frames[1].Function("thereIsNoSuchCallable()");
|
||||||
|
frames[1].document.addEventListener("myevent", f);
|
||||||
|
var frame0ErrorFired = false;
|
||||||
|
var frame1ErrorFired = false;
|
||||||
|
var ourErrorFired = false;
|
||||||
|
frames[0].addEventListener("error", function() {
|
||||||
|
frame0ErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].addEventListener("error", function() {
|
||||||
|
frame1ErrorFired = true;
|
||||||
|
});
|
||||||
|
addEventListener("error", function() {
|
||||||
|
ourErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].document.dispatchEvent(new Event("myevent"));
|
||||||
|
assert_false(frame0ErrorFired);
|
||||||
|
assert_true(frame1ErrorFired);
|
||||||
|
assert_false(ourErrorFired);
|
||||||
|
}, "The error event from an event listener should fire on that listener's global");
|
||||||
|
</script>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>
|
||||||
|
When a listener from window A is added to an event target in window A via the
|
||||||
|
addEventListener function from window B, errors in that listener should be
|
||||||
|
reported to window A.
|
||||||
|
</title>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<iframe></iframe>
|
||||||
|
<iframe></iframe>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var f = new frames[1].Function("thereIsNoSuchCallable()");
|
||||||
|
frames[0].document.addEventListener.call(frames[1].document, "myevent", f);
|
||||||
|
var frame0ErrorFired = false;
|
||||||
|
var frame1ErrorFired = false;
|
||||||
|
var ourErrorFired = false;
|
||||||
|
frames[0].addEventListener("error", function() {
|
||||||
|
frame0ErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].addEventListener("error", function() {
|
||||||
|
frame1ErrorFired = true;
|
||||||
|
});
|
||||||
|
addEventListener("error", function() {
|
||||||
|
ourErrorFired = true;
|
||||||
|
});
|
||||||
|
frames[1].document.dispatchEvent(new Event("myevent"));
|
||||||
|
assert_false(frame0ErrorFired);
|
||||||
|
assert_true(frame1ErrorFired);
|
||||||
|
assert_false(ourErrorFired);
|
||||||
|
}, "The error event from an event listener should fire on that listener's global");
|
||||||
|
</script>
|
|
@ -3,3 +3,4 @@
|
||||||
@foolip
|
@foolip
|
||||||
@shishimaru
|
@shishimaru
|
||||||
@sideshowbarker
|
@sideshowbarker
|
||||||
|
@wolenetz
|
||||||
|
|
|
@ -161,6 +161,13 @@ function resource_load(expected)
|
||||||
|
|
||||||
t["timing_attrs"].step(function test() {
|
t["timing_attrs"].step(function test() {
|
||||||
var actual = window.performance.getEntriesByName(expected.name)[0];
|
var actual = window.performance.getEntriesByName(expected.name)[0];
|
||||||
|
|
||||||
|
// Debugging bug 1263428
|
||||||
|
// Feel free to remove/overwrite this piece of code
|
||||||
|
if (actual.connectStart < actual.domainLookupEnd) {
|
||||||
|
assert_true(false, "actual: "+JSON.stringify(actual));
|
||||||
|
}
|
||||||
|
|
||||||
assert_equals(actual.redirectStart, 0, "redirectStart time");
|
assert_equals(actual.redirectStart, 0, "redirectStart time");
|
||||||
assert_equals(actual.redirectEnd, 0, "redirectEnd time");
|
assert_equals(actual.redirectEnd, 0, "redirectEnd time");
|
||||||
assert_true(actual.secureConnectionStart == undefined ||
|
assert_true(actual.secureConnectionStart == undefined ||
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-add.js');
|
service_worker_test('../script-tests/cache-add.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-delete.js');
|
service_worker_test('../script-tests/cache-delete.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-match.js');
|
service_worker_test('../script-tests/cache-match.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-matchAll.js');
|
service_worker_test('../script-tests/cache-matchAll.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-put.js');
|
service_worker_test('../script-tests/cache-put.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-storage-keys.js');
|
service_worker_test('../script-tests/cache-storage-keys.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-storage-match.js');
|
service_worker_test('../script-tests/cache-storage-match.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<meta name="timeout" content="long">
|
<meta name="timeout" content="long">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<script>
|
<script>
|
||||||
service_worker_test('../script-tests/cache-storage.js');
|
service_worker_test('../script-tests/cache-storage.js');
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
|
<link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../../service-workers/resources/test-helpers.js"></script>
|
<script src="../../service-worker/resources/test-helpers.sub.js"></script>
|
||||||
<style>iframe { display: none; }</style>
|
<style>iframe { display: none; }</style>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
|
|
@ -440,8 +440,9 @@ async_test(function(t) {
|
||||||
.then(function() { return with_iframe(scope); })
|
.then(function() { return with_iframe(scope); })
|
||||||
.then(function(f) {
|
.then(function(f) {
|
||||||
frame = f;
|
frame = f;
|
||||||
|
assert_equals(frame.contentWindow.document.body.textContent, 'default');
|
||||||
var tests = cacheTypes.map(function(type) {
|
var tests = cacheTypes.map(function(type) {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve, reject) {
|
||||||
return frame.contentWindow.fetch(scope + '=' + type,
|
return frame.contentWindow.fetch(scope + '=' + type,
|
||||||
{cache: type})
|
{cache: type})
|
||||||
.then(function(response) { return response.text(); })
|
.then(function(response) { return response.text(); })
|
||||||
|
@ -450,10 +451,25 @@ async_test(function(t) {
|
||||||
assert_equals(response_text, expected,
|
assert_equals(response_text, expected,
|
||||||
'Service Worker should respond to fetch with the correct type');
|
'Service Worker should respond to fetch with the correct type');
|
||||||
})
|
})
|
||||||
.then(resolve);
|
.then(resolve)
|
||||||
|
.catch(reject);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return Promise.all(tests);
|
})
|
||||||
|
.then(function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
frame.addEventListener('load', function onLoad() {
|
||||||
|
frame.removeEventListener('load', onLoad);
|
||||||
|
try {
|
||||||
|
assert_equals(frame.contentWindow.document.body.textContent,
|
||||||
|
'no-cache');
|
||||||
|
resolve();
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
frame.contentWindow.location.reload();
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
frame.remove();
|
frame.remove();
|
||||||
|
@ -462,5 +478,55 @@ async_test(function(t) {
|
||||||
.catch(unreached_rejection(t));
|
.catch(unreached_rejection(t));
|
||||||
}, 'Service Worker responds to fetch event with the correct cache types');
|
}, 'Service Worker responds to fetch event with the correct cache types');
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var scope = 'resources/simple.html?eventsource';
|
||||||
|
var frame;
|
||||||
|
|
||||||
|
function test_eventsource(opts) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var eventSource = new frame.contentWindow.EventSource(scope, opts);
|
||||||
|
eventSource.addEventListener('message', function(msg) {
|
||||||
|
eventSource.close();
|
||||||
|
try {
|
||||||
|
var data = JSON.parse(msg.data);
|
||||||
|
assert_equals(data.mode, 'cors',
|
||||||
|
'EventSource should make CORS requests.');
|
||||||
|
assert_equals(data.cache, 'no-store',
|
||||||
|
'EventSource should bypass the http cache.');
|
||||||
|
var expectedCredentials = opts.withCredentials ? 'include'
|
||||||
|
: 'same-origin';
|
||||||
|
assert_equals(data.credentials, expectedCredentials,
|
||||||
|
'EventSource should pass correct credentials mode.');
|
||||||
|
resolve();
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
eventSource.addEventListener('error', function(e) {
|
||||||
|
eventSource.close();
|
||||||
|
reject('The EventSource fired an error event.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
service_worker_unregister_and_register(t, worker, scope)
|
||||||
|
.then(function(reg) {
|
||||||
|
return wait_for_state(t, reg.installing, 'activated');
|
||||||
|
})
|
||||||
|
.then(function() { return with_iframe(scope); })
|
||||||
|
.then(function(f) {
|
||||||
|
frame = f;
|
||||||
|
return test_eventsource({ withCredentials: false });
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
return test_eventsource({ withCredentials: true });
|
||||||
|
})
|
||||||
|
.then(function() {
|
||||||
|
frame.remove();
|
||||||
|
return service_worker_unregister_and_done(t, scope);
|
||||||
|
})
|
||||||
|
.catch(unreached_rejection(t));
|
||||||
|
}, 'Service Worker should intercept EventSource');
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -95,6 +95,22 @@ function handleCache(event) {
|
||||||
event.respondWith(new Response(event.request.cache));
|
event.respondWith(new Response(event.request.cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleEventSource(event) {
|
||||||
|
if (event.request.mode === 'navigate') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data = {
|
||||||
|
mode: event.request.mode,
|
||||||
|
cache: event.request.cache,
|
||||||
|
credentials: event.request.credentials
|
||||||
|
};
|
||||||
|
var body = 'data:' + JSON.stringify(data) + '\n\n';
|
||||||
|
event.respondWith(new Response(body, {
|
||||||
|
headers: { 'Content-Type': 'text/event-stream' }
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
self.addEventListener('fetch', function(event) {
|
self.addEventListener('fetch', function(event) {
|
||||||
var url = event.request.url;
|
var url = event.request.url;
|
||||||
var handlers = [
|
var handlers = [
|
||||||
|
@ -112,6 +128,7 @@ self.addEventListener('fetch', function(event) {
|
||||||
{ pattern: '?used-check', fn: handleUsedCheck },
|
{ pattern: '?used-check', fn: handleUsedCheck },
|
||||||
{ pattern: '?fragment-check', fn: handleFragmentCheck },
|
{ pattern: '?fragment-check', fn: handleFragmentCheck },
|
||||||
{ pattern: '?cache', fn: handleCache },
|
{ pattern: '?cache', fn: handleCache },
|
||||||
|
{ pattern: '?eventsource', fn: handleEventSource },
|
||||||
];
|
];
|
||||||
|
|
||||||
var handler = null;
|
var handler = null;
|
||||||
|
|
|
@ -1,222 +0,0 @@
|
||||||
// Adapter for testharness.js-style tests with Service Workers
|
|
||||||
|
|
||||||
function service_worker_unregister_and_register(test, url, scope) {
|
|
||||||
if (!scope || scope.length == 0)
|
|
||||||
return Promise.reject(new Error('tests must define a scope'));
|
|
||||||
|
|
||||||
var options = { scope: scope };
|
|
||||||
return service_worker_unregister(test, scope)
|
|
||||||
.then(function() {
|
|
||||||
return navigator.serviceWorker.register(url, options);
|
|
||||||
})
|
|
||||||
.catch(unreached_rejection(test,
|
|
||||||
'unregister and register should not fail'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function service_worker_unregister(test, documentUrl) {
|
|
||||||
return navigator.serviceWorker.getRegistration(documentUrl)
|
|
||||||
.then(function(registration) {
|
|
||||||
if (registration)
|
|
||||||
return registration.unregister();
|
|
||||||
})
|
|
||||||
.catch(unreached_rejection(test, 'unregister should not fail'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function service_worker_unregister_and_done(test, scope) {
|
|
||||||
return service_worker_unregister(test, scope)
|
|
||||||
.then(test.done.bind(test));
|
|
||||||
}
|
|
||||||
|
|
||||||
function unreached_fulfillment(test, prefix) {
|
|
||||||
return test.step_func(function(result) {
|
|
||||||
var error_prefix = prefix || 'unexpected fulfillment';
|
|
||||||
assert_unreached(error_prefix + ': ' + result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rejection-specific helper that provides more details
|
|
||||||
function unreached_rejection(test, prefix) {
|
|
||||||
return test.step_func(function(error) {
|
|
||||||
var reason = error.message || error.name || error;
|
|
||||||
var error_prefix = prefix || 'unexpected rejection';
|
|
||||||
assert_unreached(error_prefix + ': ' + reason);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds an iframe to the document and returns a promise that resolves to the
|
|
||||||
// iframe when it finishes loading. The caller is responsible for removing the
|
|
||||||
// iframe later if needed.
|
|
||||||
function with_iframe(url) {
|
|
||||||
return new Promise(function(resolve) {
|
|
||||||
var frame = document.createElement('iframe');
|
|
||||||
frame.src = url;
|
|
||||||
frame.onload = function() { resolve(frame); };
|
|
||||||
document.body.appendChild(frame);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeURL(url) {
|
|
||||||
return new URL(url, self.location).toString().replace(/#.*$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function wait_for_update(test, registration) {
|
|
||||||
if (!registration || registration.unregister == undefined) {
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'wait_for_update must be passed a ServiceWorkerRegistration'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(test.step_func(function(resolve) {
|
|
||||||
registration.addEventListener('updatefound', test.step_func(function() {
|
|
||||||
resolve(registration.installing);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function wait_for_state(test, worker, state) {
|
|
||||||
if (!worker || worker.state == undefined) {
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'wait_for_state must be passed a ServiceWorker'));
|
|
||||||
}
|
|
||||||
if (worker.state === state)
|
|
||||||
return Promise.resolve(state);
|
|
||||||
|
|
||||||
if (state === 'installing') {
|
|
||||||
switch (worker.state) {
|
|
||||||
case 'installed':
|
|
||||||
case 'activating':
|
|
||||||
case 'activated':
|
|
||||||
case 'redundant':
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'worker is ' + worker.state + ' but waiting for ' + state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state === 'installed') {
|
|
||||||
switch (worker.state) {
|
|
||||||
case 'activating':
|
|
||||||
case 'activated':
|
|
||||||
case 'redundant':
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'worker is ' + worker.state + ' but waiting for ' + state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state === 'activating') {
|
|
||||||
switch (worker.state) {
|
|
||||||
case 'activated':
|
|
||||||
case 'redundant':
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'worker is ' + worker.state + ' but waiting for ' + state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state === 'activated') {
|
|
||||||
switch (worker.state) {
|
|
||||||
case 'redundant':
|
|
||||||
return Promise.reject(new Error(
|
|
||||||
'worker is ' + worker.state + ' but waiting for ' + state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(test.step_func(function(resolve) {
|
|
||||||
worker.addEventListener('statechange', test.step_func(function() {
|
|
||||||
if (worker.state === state)
|
|
||||||
resolve(state);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Declare a test that runs entirely in the ServiceWorkerGlobalScope. The |url|
|
|
||||||
// is the service worker script URL. This function:
|
|
||||||
// - Instantiates a new test with the description specified in |description|.
|
|
||||||
// The test will succeed if the specified service worker can be successfully
|
|
||||||
// registered and installed.
|
|
||||||
// - Creates a new ServiceWorker registration with a scope unique to the current
|
|
||||||
// document URL. Note that this doesn't allow more than one
|
|
||||||
// service_worker_test() to be run from the same document.
|
|
||||||
// - Waits for the new worker to begin installing.
|
|
||||||
// - Imports tests results from tests running inside the ServiceWorker.
|
|
||||||
function service_worker_test(url, description) {
|
|
||||||
// If the document URL is https://example.com/document and the script URL is
|
|
||||||
// https://example.com/script/worker.js, then the scope would be
|
|
||||||
// https://example.com/script/scope/document.
|
|
||||||
var scope = new URL('scope' + window.location.pathname,
|
|
||||||
new URL(url, window.location)).toString();
|
|
||||||
promise_test(function(test) {
|
|
||||||
return service_worker_unregister_and_register(test, url, scope)
|
|
||||||
.then(function(registration) {
|
|
||||||
add_completion_callback(function() {
|
|
||||||
registration.unregister();
|
|
||||||
});
|
|
||||||
return wait_for_update(test, registration)
|
|
||||||
.then(function(worker) {
|
|
||||||
return fetch_tests_from_worker(worker);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, description);
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_host_info() {
|
|
||||||
var ORIGINAL_HOST = '127.0.0.1';
|
|
||||||
var REMOTE_HOST = 'localhost';
|
|
||||||
var UNAUTHENTICATED_HOST = 'example.test';
|
|
||||||
var HTTP_PORT = 8000;
|
|
||||||
var HTTPS_PORT = 8443;
|
|
||||||
try {
|
|
||||||
// In W3C test, we can get the hostname and port number in config.json
|
|
||||||
// using wptserve's built-in pipe.
|
|
||||||
// http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes
|
|
||||||
HTTP_PORT = eval('{{ports[http][0]}}');
|
|
||||||
HTTPS_PORT = eval('{{ports[https][0]}}');
|
|
||||||
ORIGINAL_HOST = eval('\'{{host}}\'');
|
|
||||||
REMOTE_HOST = 'www1.' + ORIGINAL_HOST;
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT,
|
|
||||||
HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT,
|
|
||||||
HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT,
|
|
||||||
HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT,
|
|
||||||
UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function base_path() {
|
|
||||||
return location.pathname.replace(/\/[^\/]*$/, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_login(test, origin, username, password, cookie) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
with_iframe(
|
|
||||||
origin +
|
|
||||||
'/serviceworker/resources/fetch-access-control-login.html')
|
|
||||||
.then(test.step_func(function(frame) {
|
|
||||||
var channel = new MessageChannel();
|
|
||||||
channel.port1.onmessage = test.step_func(function() {
|
|
||||||
frame.remove();
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
frame.contentWindow.postMessage(
|
|
||||||
{username: username, password: password, cookie: cookie},
|
|
||||||
origin, [channel.port2]);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function login(test) {
|
|
||||||
return test_login(test, 'http://127.0.0.1:8000',
|
|
||||||
'username1', 'password1', 'cookie1')
|
|
||||||
.then(function() {
|
|
||||||
return test_login(test, 'http://localhost:8000',
|
|
||||||
'username2', 'password2', 'cookie2');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function login_https(test) {
|
|
||||||
return test_login(test, 'https://127.0.0.1:8443',
|
|
||||||
'username1s', 'password1s', 'cookie1')
|
|
||||||
.then(function() {
|
|
||||||
return test_login(test, 'https://localhost:8443',
|
|
||||||
'username2s', 'password2s', 'cookie2');
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -42,6 +42,9 @@ class Manifest(object):
|
||||||
for path in self.local_changes.iterdeleted():
|
for path in self.local_changes.iterdeleted():
|
||||||
if path in paths:
|
if path in paths:
|
||||||
del paths[path]
|
del paths[path]
|
||||||
|
if item_type == "reftest":
|
||||||
|
for path, items in self.local_changes.iterdeletedreftests():
|
||||||
|
paths[path] -= items
|
||||||
|
|
||||||
yield item_type, paths
|
yield item_type, paths
|
||||||
|
|
||||||
|
@ -170,14 +173,37 @@ class Manifest(object):
|
||||||
self.url_base = url_base
|
self.url_base = url_base
|
||||||
|
|
||||||
def update_reftests(self):
|
def update_reftests(self):
|
||||||
reftest_nodes = self.reftest_nodes.copy()
|
default_reftests = self.compute_reftests(self.reftest_nodes)
|
||||||
for path, items in self.local_changes.reftest_nodes.iteritems():
|
all_reftest_nodes = self.reftest_nodes.copy()
|
||||||
reftest_nodes[path] |= items
|
all_reftest_nodes.update(self.local_changes.reftest_nodes)
|
||||||
|
|
||||||
#TODO: remove locally deleted files
|
for item in self.local_changes.iterdeleted():
|
||||||
tests = set()
|
if item in all_reftest_nodes:
|
||||||
for items in reftest_nodes.values():
|
del all_reftest_nodes[item]
|
||||||
tests |= set(item for item in items if not item.is_reference)
|
|
||||||
|
modified_reftests = self.compute_reftests(all_reftest_nodes)
|
||||||
|
|
||||||
|
added_reftests = modified_reftests - default_reftests
|
||||||
|
# The interesting case here is not when the file is deleted,
|
||||||
|
# but when a reftest like A == B is changed to the form
|
||||||
|
# C == A == B, so that A still exists but is now a ref rather than
|
||||||
|
# a test.
|
||||||
|
removed_reftests = default_reftests - modified_reftests
|
||||||
|
|
||||||
|
dests = [(default_reftests, self._data["reftest"]),
|
||||||
|
(added_reftests, self.local_changes._data["reftest"]),
|
||||||
|
(removed_reftests, self.local_changes._deleted_reftests)]
|
||||||
|
|
||||||
|
#TODO: Warn if there exist unreachable reftest nodes
|
||||||
|
for source, target in dests:
|
||||||
|
for item in source:
|
||||||
|
target[item.path].add(item)
|
||||||
|
|
||||||
|
def compute_reftests(self, reftest_nodes):
|
||||||
|
"""Given a set of reftest_nodes, return a set of all the nodes that are top-level
|
||||||
|
tests i.e. don't have any incoming reference links."""
|
||||||
|
|
||||||
|
reftests = set()
|
||||||
|
|
||||||
has_inbound = set()
|
has_inbound = set()
|
||||||
for path, items in reftest_nodes.iteritems():
|
for path, items in reftest_nodes.iteritems():
|
||||||
|
@ -185,18 +211,13 @@ class Manifest(object):
|
||||||
for ref_url, ref_type in item.references:
|
for ref_url, ref_type in item.references:
|
||||||
has_inbound.add(ref_url)
|
has_inbound.add(ref_url)
|
||||||
|
|
||||||
if self.local_changes.reftest_nodes:
|
|
||||||
target = self.local_changes
|
|
||||||
else:
|
|
||||||
target = self
|
|
||||||
|
|
||||||
#TODO: Warn if there exist unreachable reftest nodes
|
|
||||||
|
|
||||||
for path, items in reftest_nodes.iteritems():
|
for path, items in reftest_nodes.iteritems():
|
||||||
for item in items:
|
for item in items:
|
||||||
if item.url in has_inbound:
|
if item.url in has_inbound:
|
||||||
continue
|
continue
|
||||||
target._data["reftest"][path].add(item)
|
reftests.add(item)
|
||||||
|
|
||||||
|
return reftests
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
out_items = {
|
out_items = {
|
||||||
|
@ -261,6 +282,7 @@ class Manifest(object):
|
||||||
source_files=source_files)
|
source_files=source_files)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class LocalChanges(object):
|
class LocalChanges(object):
|
||||||
def __init__(self, manifest):
|
def __init__(self, manifest):
|
||||||
self.manifest = manifest
|
self.manifest = manifest
|
||||||
|
@ -268,6 +290,7 @@ class LocalChanges(object):
|
||||||
self._deleted = set()
|
self._deleted = set()
|
||||||
self.reftest_nodes = defaultdict(set)
|
self.reftest_nodes = defaultdict(set)
|
||||||
self.reftest_nodes_by_url = {}
|
self.reftest_nodes_by_url = {}
|
||||||
|
self._deleted_reftests = defaultdict(set)
|
||||||
|
|
||||||
def add(self, item):
|
def add(self, item):
|
||||||
if item is None:
|
if item is None:
|
||||||
|
@ -305,6 +328,10 @@ class LocalChanges(object):
|
||||||
for item in self._deleted:
|
for item in self._deleted:
|
||||||
yield item
|
yield item
|
||||||
|
|
||||||
|
def iterdeletedreftests(self):
|
||||||
|
for item in self._deleted_reftests.iteritems():
|
||||||
|
yield item
|
||||||
|
|
||||||
def __getitem__(self, item_type):
|
def __getitem__(self, item_type):
|
||||||
return self._data[item_type]
|
return self._data[item_type]
|
||||||
|
|
||||||
|
@ -312,9 +339,13 @@ class LocalChanges(object):
|
||||||
reftest_nodes = {from_os_path(key): [v.to_json() for v in value]
|
reftest_nodes = {from_os_path(key): [v.to_json() for v in value]
|
||||||
for key, value in self.reftest_nodes.iteritems()}
|
for key, value in self.reftest_nodes.iteritems()}
|
||||||
|
|
||||||
|
deleted_reftests = {from_os_path(key): [v.to_json() for v in value]
|
||||||
|
for key, value in self._deleted_reftests.iteritems()}
|
||||||
|
|
||||||
rv = {"items": defaultdict(dict),
|
rv = {"items": defaultdict(dict),
|
||||||
"reftest_nodes": reftest_nodes,
|
"reftest_nodes": reftest_nodes,
|
||||||
"deleted": [from_os_path(path) for path in self._deleted]}
|
"deleted": [from_os_path(path) for path in self._deleted],
|
||||||
|
"deleted_reftests": deleted_reftests}
|
||||||
|
|
||||||
for test_type, paths in self._data.iteritems():
|
for test_type, paths in self._data.iteritems():
|
||||||
for path, tests in paths.iteritems():
|
for path, tests in paths.iteritems():
|
||||||
|
@ -355,6 +386,13 @@ class LocalChanges(object):
|
||||||
for item in obj["deleted"]:
|
for item in obj["deleted"]:
|
||||||
self.add_deleted(to_os_path(item))
|
self.add_deleted(to_os_path(item))
|
||||||
|
|
||||||
|
for path, values in obj.get("deleted_reftests", {}).iteritems():
|
||||||
|
path = to_os_path(path)
|
||||||
|
for v in values:
|
||||||
|
item = RefTest.from_json(self.manifest, tests_root, v,
|
||||||
|
source_files=source_files)
|
||||||
|
self._deleted_reftests[path].add(item)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def load(tests_root, manifest):
|
def load(tests_root, manifest):
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
from .. import manifest, item as manifestitem, sourcefile
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_reftest_add():
|
||||||
|
m = manifest.Manifest()
|
||||||
|
s = sourcefile.SourceFile("/", "test", "/")
|
||||||
|
test = manifestitem.RefTest(s, "/test", [("/ref", "==")])
|
||||||
|
m.local_changes.add(test)
|
||||||
|
assert list(m) == [(test.path, {test})]
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_reftest_delete_path():
|
||||||
|
m = manifest.Manifest()
|
||||||
|
s = sourcefile.SourceFile("/", "test", "/")
|
||||||
|
test = manifestitem.RefTest(s, "/test", [("/ref", "==")])
|
||||||
|
m.add(test)
|
||||||
|
m.local_changes.add_deleted(test.path)
|
||||||
|
assert list(m) == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_reftest_adjusted():
|
||||||
|
m = manifest.Manifest()
|
||||||
|
s = sourcefile.SourceFile("/", "test", "/")
|
||||||
|
test = manifestitem.RefTest(s, "/test", [("/ref", "==")])
|
||||||
|
m.add(test)
|
||||||
|
|
||||||
|
assert list(m) == [(test.path, {test})]
|
||||||
|
|
||||||
|
assert m.compute_reftests({test.path: {test}}) == {test}
|
||||||
|
|
||||||
|
test_1 = manifestitem.RefTest(s, "/test-1", [("/test", "==")])
|
||||||
|
m.local_changes.add(test_1)
|
||||||
|
|
||||||
|
assert m.compute_reftests({test.path: {test}, test_1.path: {test_1}}) == {test_1}
|
||||||
|
|
||||||
|
m.local_changes._deleted_reftests[test.path] = {test}
|
||||||
|
|
||||||
|
assert list(m) == [(test_1.path, {test_1})]
|
||||||
|
|
||||||
|
|
||||||
|
def test_manifest_to_json():
|
||||||
|
m = manifest.Manifest()
|
||||||
|
s = sourcefile.SourceFile("/", "test", "/")
|
||||||
|
test = manifestitem.RefTest(s, "/test", [("/ref", "==")])
|
||||||
|
m.add(test)
|
||||||
|
test_1 = manifestitem.RefTest(s, "/test-1", [("/test", "==")])
|
||||||
|
m.local_changes.add(test_1)
|
||||||
|
m.local_changes._deleted_reftests[test.path] = {test}
|
||||||
|
|
||||||
|
json_str = m.to_json()
|
||||||
|
loaded = manifest.Manifest.from_json("/", json_str)
|
||||||
|
|
||||||
|
assert list(loaded) == list(m)
|
||||||
|
|
||||||
|
assert loaded.to_json() == json_str
|
|
@ -0,0 +1,81 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Focus-related events should fire in the correct order</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="https://w3c.github.io/uievents/#events-focusevent-event-order">
|
||||||
|
<meta name="flags" content="interact">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ol>
|
||||||
|
<li>Click into the first text input.</li>
|
||||||
|
<li>Click into the second text input.</li>
|
||||||
|
<li>Click the "Done" button.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<input type="text" id="a" value="First">
|
||||||
|
<br>
|
||||||
|
<input type="text" id="b" value="Second">
|
||||||
|
<br>
|
||||||
|
<button type="button" id="done">Done</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setup({explicit_timeout: true});
|
||||||
|
var done = false;
|
||||||
|
var events = [];
|
||||||
|
var targets = [];
|
||||||
|
function record(e) {
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
events.push(e.type);
|
||||||
|
targets.push(e.target.id);
|
||||||
|
}
|
||||||
|
function finish() {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
var relevantEvents = [
|
||||||
|
'focus',
|
||||||
|
'blur',
|
||||||
|
'focusin',
|
||||||
|
'focusout'
|
||||||
|
];
|
||||||
|
window.onload = function () {
|
||||||
|
var a = document.getElementById('a');
|
||||||
|
var b = document.getElementById('b');
|
||||||
|
var inputs = [a, b];
|
||||||
|
|
||||||
|
b.addEventListener('blur', finish, false);
|
||||||
|
b.addEventListener('focusout', finish, false);
|
||||||
|
|
||||||
|
for (var i = 0; i < inputs.length; i++) {
|
||||||
|
for (var k = 0; k < relevantEvents.length; k++) {
|
||||||
|
inputs[i].addEventListener(relevantEvents[k], record, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
document.getElementById('done').addEventListener('click', function () {
|
||||||
|
finish();
|
||||||
|
t.step(function () {
|
||||||
|
assert_array_equals(
|
||||||
|
events,
|
||||||
|
['focusin', 'focus', 'focusout', 'focusin', 'blur', 'focus'],
|
||||||
|
'Focus-related events should fire in this order: focusin, focus, focusout, focusin, blur, focus'
|
||||||
|
);
|
||||||
|
assert_array_equals(
|
||||||
|
targets,
|
||||||
|
[ 'a', 'a', 'a', 'b', 'a', 'b'],
|
||||||
|
'Focus-related events should fire at the correct targets'
|
||||||
|
);
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
}, false);
|
||||||
|
}, 'Focus-related events should fire in the correct order');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,84 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Focus-related events (including legacy events) should fire in the correct order</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="https://w3c.github.io/uievents/#legacy-focusevent-event-order">
|
||||||
|
<meta name="flags" content="interact">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ol>
|
||||||
|
<li>Click into the first text input.</li>
|
||||||
|
<li>Click into the second text input.</li>
|
||||||
|
<li>Click the "Done" button.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<input type="text" id="a" value="First">
|
||||||
|
<br>
|
||||||
|
<input type="text" id="b" value="Second">
|
||||||
|
<br>
|
||||||
|
<button type="button" id="done">Done</button>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
setup({explicit_timeout: true});
|
||||||
|
var done = false;
|
||||||
|
var events = [];
|
||||||
|
var targets = [];
|
||||||
|
function record(e) {
|
||||||
|
if (done) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
events.push(e.type);
|
||||||
|
targets.push(e.target.id);
|
||||||
|
}
|
||||||
|
function finish() {
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
var relevantEvents = [
|
||||||
|
'focus',
|
||||||
|
'blur',
|
||||||
|
'focusin',
|
||||||
|
'focusout',
|
||||||
|
'DOMFocusIn',
|
||||||
|
'DOMFocusOut'
|
||||||
|
];
|
||||||
|
window.onload = function () {
|
||||||
|
var a = document.getElementById('a');
|
||||||
|
var b = document.getElementById('b');
|
||||||
|
var inputs = [a, b];
|
||||||
|
|
||||||
|
b.addEventListener('blur', finish, false);
|
||||||
|
b.addEventListener('focusout', finish, false);
|
||||||
|
b.addEventListener('DOMFocusOut', finish, false);
|
||||||
|
|
||||||
|
for (var i = 0; i < inputs.length; i++) {
|
||||||
|
for (var k = 0; k < relevantEvents.length; k++) {
|
||||||
|
inputs[i].addEventListener(relevantEvents[k], record, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
document.getElementById('done').addEventListener('click', function () {
|
||||||
|
finish();
|
||||||
|
t.step(function () {
|
||||||
|
assert_array_equals(
|
||||||
|
events,
|
||||||
|
['focusin', 'focus', 'DOMFocusIn', 'focusout', 'focusin', 'blur', 'DOMFocusOut', 'focus', 'DOMFocusIn'],
|
||||||
|
'Focus-related events should fire in this order: focusin, focus, DOMFocusIn, focusout, focusin, blur, DOMFocusOut, focus, DOMFocusIn'
|
||||||
|
);
|
||||||
|
assert_array_equals(
|
||||||
|
targets,
|
||||||
|
[ 'a', 'a', 'a', 'a', 'b', 'a', 'a', 'b', 'b'],
|
||||||
|
'Focus-related events should fire at the correct targets'
|
||||||
|
);
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
}, false);
|
||||||
|
}, 'Focus-related events should fire in the correct order');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,84 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>easing tests</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-easing">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<script src="../resources/effect-easing-tests.js"></script>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function assert_progress(animation, currentTime, easingFunction) {
|
||||||
|
animation.currentTime = currentTime;
|
||||||
|
var portion = currentTime / animation.effect.timing.duration;
|
||||||
|
assert_approx_equals(animation.effect.getComputedTiming().progress,
|
||||||
|
easingFunction(portion),
|
||||||
|
0.01,
|
||||||
|
'The progress of the animation should be approximately ' +
|
||||||
|
easingFunction(portion) + ' at ' + currentTime + 'ms');
|
||||||
|
}
|
||||||
|
|
||||||
|
gEffectEasingTests.forEach(function(options) {
|
||||||
|
test(function(t) {
|
||||||
|
var target = createDiv(t);
|
||||||
|
var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
|
||||||
|
{ duration: 1000 * MS_PER_SEC,
|
||||||
|
fill: 'forwards' });
|
||||||
|
anim.effect.timing.easing = options.easing;
|
||||||
|
assert_equals(anim.effect.timing.easing, options.easing);
|
||||||
|
|
||||||
|
var easing = options.easingFunction;
|
||||||
|
assert_progress(anim, 0, easing);
|
||||||
|
assert_progress(anim, 250 * MS_PER_SEC, easing);
|
||||||
|
assert_progress(anim, 500 * MS_PER_SEC, easing);
|
||||||
|
assert_progress(anim, 750 * MS_PER_SEC, easing);
|
||||||
|
assert_progress(anim, 1000 * MS_PER_SEC, easing);
|
||||||
|
}, options.desc);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
|
||||||
|
assert_throws({ name: 'TypeError' },
|
||||||
|
function() {
|
||||||
|
anim.effect.timing.easing = '';
|
||||||
|
});
|
||||||
|
assert_throws({ name: 'TypeError' },
|
||||||
|
function() {
|
||||||
|
anim.effect.timing.easing = 'test';
|
||||||
|
});
|
||||||
|
}, 'Test invalid easing value');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var delay = 1000 * MS_PER_SEC;
|
||||||
|
|
||||||
|
var target = createDiv(t);
|
||||||
|
var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
|
||||||
|
{ duration: 1000 * MS_PER_SEC,
|
||||||
|
fill: 'both',
|
||||||
|
delay: delay,
|
||||||
|
easing: 'steps(2, start)' });
|
||||||
|
|
||||||
|
anim.effect.timing.easing = 'steps(2, end)';
|
||||||
|
assert_equals(anim.effect.getComputedTiming().progress, 0,
|
||||||
|
'easing replace to steps(2, end) at before phase');
|
||||||
|
|
||||||
|
anim.currentTime = delay + 750 * MS_PER_SEC;
|
||||||
|
assert_equals(anim.effect.getComputedTiming().progress, 0.5,
|
||||||
|
'change currentTime to active phase');
|
||||||
|
|
||||||
|
anim.effect.timing.easing = 'steps(2, start)';
|
||||||
|
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||||
|
'easing replace to steps(2, start) at active phase');
|
||||||
|
|
||||||
|
anim.currentTime = delay + 1500 * MS_PER_SEC;
|
||||||
|
anim.effect.timing.easing = 'steps(2, end)';
|
||||||
|
assert_equals(anim.effect.getComputedTiming().progress, 1,
|
||||||
|
'easing replace to steps(2, end) again at after phase');
|
||||||
|
}, 'Change the easing while the animation is running');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>fill tests</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-fill">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
["none", "forwards", "backwards", "both", ].forEach(function(fill){
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
|
||||||
|
anim.effect.timing.fill = fill;
|
||||||
|
assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill);
|
||||||
|
assert_equals(anim.effect.getComputedTiming().fill, fill, 'getComputedTiming() after set fill ' + fill);
|
||||||
|
}, 'set fill ' + fill);
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,136 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Tests for discrete animation</title>
|
||||||
|
<link rel="help" href="http://w3c.github.io/web-animations/#animatable-as-string-section">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
|
||||||
|
var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
|
||||||
|
{ duration: 1000, fill: 'forwards' });
|
||||||
|
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'normal',
|
||||||
|
'Animation produces \'from\' value at start of interval');
|
||||||
|
anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'normal',
|
||||||
|
'Animation produces \'from\' value just before the middle of'
|
||||||
|
+ ' the interval');
|
||||||
|
anim.currentTime++;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'to\' value at exact middle of'
|
||||||
|
+ ' the interval');
|
||||||
|
anim.finish();
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'to\' value during forwards fill');
|
||||||
|
}, 'Test animating discrete values');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var originalHeight = getComputedStyle(div).height;
|
||||||
|
|
||||||
|
var anim = div.animate({ height: [ 'auto', '200px' ] },
|
||||||
|
{ duration: 1000, fill: 'forwards' });
|
||||||
|
|
||||||
|
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||||
|
'Animation produces \'from\' value at start of interval');
|
||||||
|
anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
|
||||||
|
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||||
|
'Animation produces \'from\' value just before the middle of'
|
||||||
|
+ ' the interval');
|
||||||
|
anim.currentTime++;
|
||||||
|
assert_equals(getComputedStyle(div).height, '200px',
|
||||||
|
'Animation produces \'to\' value at exact middle of'
|
||||||
|
+ ' the interval');
|
||||||
|
anim.finish();
|
||||||
|
assert_equals(getComputedStyle(div).height, '200px',
|
||||||
|
'Animation produces \'to\' value during forwards fill');
|
||||||
|
}, 'Test discrete animation is used when interpolation fails');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var originalHeight = getComputedStyle(div).height;
|
||||||
|
|
||||||
|
var anim = div.animate({ height: [ 'auto',
|
||||||
|
'200px',
|
||||||
|
'300px',
|
||||||
|
'auto',
|
||||||
|
'400px' ] },
|
||||||
|
{ duration: 1000, fill: 'forwards' });
|
||||||
|
|
||||||
|
// There are five values, so there are four pairs to try to interpolate.
|
||||||
|
// We test at the middle of each pair.
|
||||||
|
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||||
|
'Animation produces \'from\' value at start of interval');
|
||||||
|
anim.currentTime = 125;
|
||||||
|
assert_equals(getComputedStyle(div).height, '200px',
|
||||||
|
'First non-interpolable pair uses discrete interpolation');
|
||||||
|
anim.currentTime += 250;
|
||||||
|
assert_equals(getComputedStyle(div).height, '250px',
|
||||||
|
'Second interpolable pair uses linear interpolation');
|
||||||
|
anim.currentTime += 250;
|
||||||
|
assert_equals(getComputedStyle(div).height, originalHeight,
|
||||||
|
'Third non-interpolable pair uses discrete interpolation');
|
||||||
|
anim.currentTime += 250;
|
||||||
|
assert_equals(getComputedStyle(div).height, '400px',
|
||||||
|
'Fourth non-interpolable pair uses discrete interpolation');
|
||||||
|
}, 'Test discrete animation is used only for pairs of values that cannot'
|
||||||
|
+ ' be interpolated');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var originalHeight = getComputedStyle(div).height;
|
||||||
|
|
||||||
|
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||||
|
// With this curve, we don't reach the 50% point until about 95% of
|
||||||
|
// the time has expired.
|
||||||
|
var anim = div.animate({ fontStyle: [ 'italic', 'oblique' ] },
|
||||||
|
{ duration: 1000, fill: 'forwards',
|
||||||
|
easing: 'cubic-bezier(0.68,0,1,0.01)' });
|
||||||
|
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'from\' value at start of interval');
|
||||||
|
anim.currentTime = 940;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'from\' value at 94% of the iteration'
|
||||||
|
+ ' time');
|
||||||
|
anim.currentTime = 960;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'oblique',
|
||||||
|
'Animation produces \'to\' value at 96% of the iteration'
|
||||||
|
+ ' time');
|
||||||
|
}, 'Test the 50% switch point for discrete animation is based on the'
|
||||||
|
+ ' effect easing');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var originalHeight = getComputedStyle(div).height;
|
||||||
|
|
||||||
|
// Easing: http://cubic-bezier.com/#.68,0,1,.01
|
||||||
|
// With this curve, we don't reach the 50% point until about 95% of
|
||||||
|
// the time has expired.
|
||||||
|
var anim = div.animate([ { fontStyle: 'italic',
|
||||||
|
easing: 'cubic-bezier(0.68,0,1,0.01)' },
|
||||||
|
{ fontStyle: 'oblique' } ],
|
||||||
|
{ duration: 1000, fill: 'forwards' });
|
||||||
|
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'from\' value at start of interval');
|
||||||
|
anim.currentTime = 940;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'italic',
|
||||||
|
'Animation produces \'from\' value at 94% of the iteration'
|
||||||
|
+ ' time');
|
||||||
|
anim.currentTime = 960;
|
||||||
|
assert_equals(getComputedStyle(div).fontStyle, 'oblique',
|
||||||
|
'Animation produces \'to\' value at 96% of the iteration'
|
||||||
|
+ ' time');
|
||||||
|
}, 'Test the 50% switch point for discrete animation is based on the'
|
||||||
|
+ ' keyframe easing');
|
||||||
|
|
||||||
|
</script>
|
|
@ -0,0 +1,120 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Tests for not animatable properties</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#not-animatable-section">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../testcommon.js"></script>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate({ display: [ 'inline', 'inline-block' ] }, 1000);
|
||||||
|
|
||||||
|
assert_equals(anim.effect.getFrames().length, 0,
|
||||||
|
'Animation specified using property-indexed notation but'
|
||||||
|
+ ' consisting of only non-animatable properties should not'
|
||||||
|
+ ' contain any keyframes');
|
||||||
|
}, '\'display\' property cannot be animated using property-indexed notation');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate([ { display: 'inline' }, { display: 'inline-block' } ],
|
||||||
|
1000);
|
||||||
|
|
||||||
|
assert_equals(anim.effect.getFrames().length, 2,
|
||||||
|
'Animation specified using a keyframe sequence where each'
|
||||||
|
+ ' keyframe contains only non-animatable properties should'
|
||||||
|
+ ' return an equal number of (empty) keyframes');
|
||||||
|
assert_false(anim.effect.getFrames()[0].hasOwnProperty('display'),
|
||||||
|
'Initial keyframe should not have the \'display\' property');
|
||||||
|
assert_false(anim.effect.getFrames()[1].hasOwnProperty('display'),
|
||||||
|
'Final keyframe should not have the \'display\' property');
|
||||||
|
}, '\'display\' property cannot be animated using a keyframe sequence');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var properties = {
|
||||||
|
// CSS Animations properties
|
||||||
|
animation: [ 'anim 1s', 'anim 2s' ],
|
||||||
|
animationName: [ 'abc', 'xyz' ],
|
||||||
|
animationTimingFunction: [ 'ease', 'steps(2)' ],
|
||||||
|
animationDelay: [ '1s', '2s' ],
|
||||||
|
animationIterationCount: [ 1, 2 ],
|
||||||
|
animationDirection: [ 'normal', 'reverse' ],
|
||||||
|
animationFillMode: [ 'forwards', 'backwards' ],
|
||||||
|
animationPlayState: [ 'paused', 'running' ],
|
||||||
|
|
||||||
|
// CSS Transitions properties
|
||||||
|
transition: [ 'all 1s', 'all 2s' ],
|
||||||
|
transitionDelay: [ '1s', '2s' ],
|
||||||
|
transitionDuration: [ '1s', '2s' ],
|
||||||
|
transitionProperty: [ 'all', 'opacity' ],
|
||||||
|
transitionTimingFunction: [ 'ease', 'ease-out' ]
|
||||||
|
};
|
||||||
|
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate(properties, 1000);
|
||||||
|
|
||||||
|
assert_equals(anim.effect.getFrames().length, 0,
|
||||||
|
'Animation specified using property-indexed notation but'
|
||||||
|
+ ' consisting of only non-animatable properties should not'
|
||||||
|
+ ' contain any keyframes');
|
||||||
|
}, 'CSS animations and CSS transitions properties cannot be animated using'
|
||||||
|
+ ' property-indexed notation');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var frames = [
|
||||||
|
{
|
||||||
|
animation: 'anim 1s',
|
||||||
|
animationName: 'abc',
|
||||||
|
animationTimingFunction: 'ease',
|
||||||
|
animationDelay: '1s',
|
||||||
|
animationIterationCount: 1,
|
||||||
|
animationDirection: 'normal',
|
||||||
|
animationFillMode: 'forwards',
|
||||||
|
animationPlayState: 'paused',
|
||||||
|
transition: 'all 1s',
|
||||||
|
transitionDelay: '1s',
|
||||||
|
transitionDuration: '1s',
|
||||||
|
transitionProperty: 'opacity',
|
||||||
|
transitionTimingFunction: 'ease'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
animation: 'anim 2s',
|
||||||
|
animationName: 'xyz',
|
||||||
|
animationTimingFunction: 'steps(2)',
|
||||||
|
animationDelay: '2s',
|
||||||
|
animationIterationCount: 2,
|
||||||
|
animationDirection: 'reverse',
|
||||||
|
animationFillMode: 'backwards',
|
||||||
|
animationPlayState: 'running',
|
||||||
|
transition: 'all 2s',
|
||||||
|
transitionDelay: '2s',
|
||||||
|
transitionDuration: '2s',
|
||||||
|
transitionProperty: 'all',
|
||||||
|
transitionTimingFunction: 'ease-out'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var defaultKeyframeProperties = [ 'computedOffset', 'easing', 'offset' ];
|
||||||
|
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate(frames, 1000);
|
||||||
|
|
||||||
|
assert_equals(anim.effect.getFrames().length, 2,
|
||||||
|
'Animation specified using a keyframe sequence where each'
|
||||||
|
+ ' keyframe contains only non-animatable properties should'
|
||||||
|
+ ' return an equal number of (empty) keyframes');
|
||||||
|
assert_array_equals(Object.keys(anim.effect.getFrames()[0]),
|
||||||
|
defaultKeyframeProperties,
|
||||||
|
'Initial keyframe should not contain any properties other'
|
||||||
|
+ ' than the default keyframe properties');
|
||||||
|
assert_array_equals(Object.keys(anim.effect.getFrames()[1]),
|
||||||
|
defaultKeyframeProperties,
|
||||||
|
'Final keyframe should not contain any properties other'
|
||||||
|
+ ' than the default keyframe properties');
|
||||||
|
}, 'CSS animations and CSS transitions properties cannot be animated using'
|
||||||
|
+ ' a sequence of keyframes');
|
||||||
|
</script>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Tests that property values respond to changes to their context</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
div.style.fontSize = '10px';
|
||||||
|
var animation = div.animate([ { marginLeft: '10em' },
|
||||||
|
{ marginLeft: '20em' } ], 1000);
|
||||||
|
animation.currentTime = 500;
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||||
|
'Effect value before updating font-size');
|
||||||
|
div.style.fontSize = '20px';
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||||
|
'Effect value after updating font-size');
|
||||||
|
}, 'Effect values reflect changes to font-size on element');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var parentDiv = createDiv(t);
|
||||||
|
var div = createDiv(t);
|
||||||
|
parentDiv.appendChild(div);
|
||||||
|
parentDiv.style.fontSize = '10px';
|
||||||
|
|
||||||
|
var animation = div.animate([ { marginLeft: '10em' },
|
||||||
|
{ marginLeft: '20em' } ], 1000);
|
||||||
|
animation.currentTime = 500;
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||||
|
'Effect value before updating font-size on parent element');
|
||||||
|
parentDiv.style.fontSize = '20px';
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||||
|
'Effect value after updating font-size on parent element');
|
||||||
|
}, 'Effect values reflect changes to font-size on parent element');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var parentDiv = createDiv(t);
|
||||||
|
var div = createDiv(t);
|
||||||
|
parentDiv.appendChild(div);
|
||||||
|
parentDiv.style.fontSize = '10px';
|
||||||
|
var animation = div.animate([ { marginLeft: '10em' },
|
||||||
|
{ marginLeft: '20em' } ], 1000);
|
||||||
|
|
||||||
|
animation.pause();
|
||||||
|
animation.currentTime = 500;
|
||||||
|
parentDiv.style.fontSize = '20px';
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||||
|
'Effect value after updating font-size on parent element');
|
||||||
|
});
|
||||||
|
}, 'Effect values reflect changes to font-size when computed style is not'
|
||||||
|
+ ' immediately flushed');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var divWith10pxFontSize = createDiv(t);
|
||||||
|
divWith10pxFontSize.style.fontSize = '10px';
|
||||||
|
var divWith20pxFontSize = createDiv(t);
|
||||||
|
divWith20pxFontSize.style.fontSize = '20px';
|
||||||
|
|
||||||
|
var div = createDiv(t);
|
||||||
|
div.remove(); // Detach
|
||||||
|
var animation = div.animate([ { marginLeft: '10em' },
|
||||||
|
{ marginLeft: '20em' } ], 1000);
|
||||||
|
animation.pause();
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 500;
|
||||||
|
|
||||||
|
divWith10pxFontSize.appendChild(div);
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '150px',
|
||||||
|
'Effect value after attaching to font-size:10px parent');
|
||||||
|
divWith20pxFontSize.appendChild(div);
|
||||||
|
assert_equals(getComputedStyle(div).marginLeft, '300px',
|
||||||
|
'Effect value after attaching to font-size:20px parent');
|
||||||
|
});
|
||||||
|
}, 'Effect values reflect changes to font-size from reparenting');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,371 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.finished</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finished">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is the same object when playing starts');
|
||||||
|
animation.pause();
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise does not change when pausing');
|
||||||
|
animation.play();
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise does not change when play() unpauses');
|
||||||
|
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
|
||||||
|
return animation.finished;
|
||||||
|
}).then(function() {
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is the same object when playing completes');
|
||||||
|
});
|
||||||
|
}, 'Test pausing then playing does not change the finished promise');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function() {
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is the same object when playing completes');
|
||||||
|
animation.play();
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise changes when replaying animation');
|
||||||
|
|
||||||
|
previousFinishedPromise = animation.finished;
|
||||||
|
animation.play();
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is the same after redundant play() call');
|
||||||
|
|
||||||
|
});
|
||||||
|
}, 'Test restarting a finished animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise;
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function() {
|
||||||
|
previousFinishedPromise = animation.finished;
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise should be replaced when reversing a ' +
|
||||||
|
'finished promise');
|
||||||
|
animation.currentTime = 0;
|
||||||
|
return animation.finished;
|
||||||
|
}).then(function() {
|
||||||
|
previousFinishedPromise = animation.finished;
|
||||||
|
animation.play();
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is replaced after play() call on ' +
|
||||||
|
'finished, reversed animation');
|
||||||
|
});
|
||||||
|
}, 'Test restarting a reversed finished animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC + 1000;
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise is unchanged jumping past end of ' +
|
||||||
|
'finished animation');
|
||||||
|
});
|
||||||
|
}, 'Test redundant finishing of animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
// Setup callback to run if finished promise is resolved
|
||||||
|
var finishPromiseResolved = false;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
finishPromiseResolved = true;
|
||||||
|
});
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
// Jump to mid-way in interval and pause
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
animation.pause();
|
||||||
|
return animation.ready;
|
||||||
|
}).then(function() {
|
||||||
|
// Jump to the end
|
||||||
|
// (But don't use finish() since that should unpause as well)
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
}).then(function() {
|
||||||
|
assert_false(finishPromiseResolved,
|
||||||
|
'Finished promise should not resolve when paused');
|
||||||
|
});
|
||||||
|
}, 'Finished promise does not resolve when paused');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
// Setup callback to run if finished promise is resolved
|
||||||
|
var finishPromiseResolved = false;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
finishPromiseResolved = true;
|
||||||
|
});
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
// Jump to mid-way in interval and pause
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
animation.pause();
|
||||||
|
// Jump to the end
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
}).then(function() {
|
||||||
|
assert_false(finishPromiseResolved,
|
||||||
|
'Finished promise should not resolve when pause-pending');
|
||||||
|
});
|
||||||
|
}, 'Finished promise does not resolve when pause-pending');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function(resolvedAnimation) {
|
||||||
|
assert_equals(resolvedAnimation, animation,
|
||||||
|
'Object identity of animation passed to Promise callback'
|
||||||
|
+ ' matches the animation object owning the Promise');
|
||||||
|
});
|
||||||
|
}, 'The finished promise is fulfilled with its Animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
|
||||||
|
// Set up listeners on finished promise
|
||||||
|
var retPromise = animation.finished.then(function() {
|
||||||
|
assert_unreached('finished promise was fulfilled');
|
||||||
|
}).catch(function(err) {
|
||||||
|
assert_equals(err.name, 'AbortError',
|
||||||
|
'finished promise is rejected with AbortError');
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise should change after the original is ' +
|
||||||
|
'rejected');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.cancel();
|
||||||
|
|
||||||
|
return retPromise;
|
||||||
|
}, 'finished promise is rejected when an animation is cancelled by calling ' +
|
||||||
|
'cancel()');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function() {
|
||||||
|
animation.cancel();
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'A new finished promise should be created when'
|
||||||
|
+ ' cancelling a finished animation');
|
||||||
|
});
|
||||||
|
}, 'cancelling an already-finished animation replaces the finished promise');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.cancel();
|
||||||
|
// The spec says we still create a new finished promise and reject the old
|
||||||
|
// one even if we're already idle. That behavior might change, but for now
|
||||||
|
// test that we do that.
|
||||||
|
var retPromise = animation.finished.catch(function(err) {
|
||||||
|
assert_equals(err.name, 'AbortError',
|
||||||
|
'finished promise is rejected with AbortError');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Redundant call to cancel();
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.cancel();
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'A redundant call to cancel() should still generate a new'
|
||||||
|
+ ' finished promise');
|
||||||
|
return retPromise;
|
||||||
|
}, 'cancelling an idle animation still replaces the finished promise');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
const HALF_DUR = 100 * MS_PER_SEC / 2;
|
||||||
|
const QUARTER_DUR = 100 * MS_PER_SEC / 4;
|
||||||
|
var gotNextFrame = false;
|
||||||
|
var currentTimeBeforeShortening;
|
||||||
|
animation.currentTime = HALF_DUR;
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
currentTimeBeforeShortening = animation.currentTime;
|
||||||
|
animation.effect.timing.duration = QUARTER_DUR;
|
||||||
|
// Below we use gotNextFrame to check that shortening of the animation
|
||||||
|
// duration causes the finished promise to resolve, rather than it just
|
||||||
|
// getting resolved on the next animation frame. This relies on the fact
|
||||||
|
// that the promises are resolved as a micro-task before the next frame
|
||||||
|
// happens.
|
||||||
|
waitForAnimationFrames(1).then(function() {
|
||||||
|
gotNextFrame = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return animation.finished;
|
||||||
|
}).then(function() {
|
||||||
|
assert_false(gotNextFrame, 'shortening of the animation duration should ' +
|
||||||
|
'resolve the finished promise');
|
||||||
|
assert_equals(animation.currentTime, currentTimeBeforeShortening,
|
||||||
|
'currentTime should be unchanged when duration shortened');
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.effect.timing.duration = 100 * MS_PER_SEC;
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise should change after lengthening the ' +
|
||||||
|
'duration causes the animation to become active');
|
||||||
|
});
|
||||||
|
}, 'Test finished promise changes for animation duration changes');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var retPromise = animation.ready.then(function() {
|
||||||
|
animation.playbackRate = 0;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC + 1000;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.finished.then(t.step_func(function() {
|
||||||
|
assert_unreached('finished promise should not resolve when playbackRate ' +
|
||||||
|
'is zero');
|
||||||
|
}));
|
||||||
|
|
||||||
|
return retPromise;
|
||||||
|
}, 'Test finished promise changes when playbackRate == 0');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
return animation.finished;
|
||||||
|
});
|
||||||
|
}, 'Test finished promise resolves when reaching to the natural boundary.');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.finish();
|
||||||
|
return animation.finished.then(function() {
|
||||||
|
animation.currentTime = 0;
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'Finished promise should change once a prior ' +
|
||||||
|
'finished promise resolved and the animation ' +
|
||||||
|
'falls out finished state');
|
||||||
|
});
|
||||||
|
}, 'Test finished promise changes when a prior finished promise resolved ' +
|
||||||
|
'and the animation falls out finished state');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
assert_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'No new finished promise generated when finished state ' +
|
||||||
|
'is checked asynchronously');
|
||||||
|
}, 'Test no new finished promise generated when finished state ' +
|
||||||
|
'is checked asynchronously');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var previousFinishedPromise = animation.finished;
|
||||||
|
animation.finish();
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||||
|
'New finished promise generated when finished state ' +
|
||||||
|
'is checked synchronously');
|
||||||
|
}, 'Test new finished promise generated when finished state ' +
|
||||||
|
'is checked synchronously');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var resolvedFinished = false;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
resolvedFinished = true;
|
||||||
|
});
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.finish();
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
}).then(function() {
|
||||||
|
assert_true(resolvedFinished,
|
||||||
|
'Animation.finished should be resolved even if ' +
|
||||||
|
'the finished state is changed soon');
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 'Test synchronous finished promise resolved even if finished state ' +
|
||||||
|
'is changed soon');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var resolvedFinished = false;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
resolvedFinished = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
animation.finish();
|
||||||
|
}).then(function() {
|
||||||
|
assert_true(resolvedFinished,
|
||||||
|
'Animation.finished should be resolved soon after finish() is ' +
|
||||||
|
'called even if there are other asynchronous promises just before it');
|
||||||
|
});
|
||||||
|
}, 'Test synchronous finished promise resolved even if asynchronous ' +
|
||||||
|
'finished promise happens just before synchronous promise');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.finished.then(t.step_func(function() {
|
||||||
|
assert_unreached('Animation.finished should not be resolved');
|
||||||
|
}));
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
});
|
||||||
|
}, 'Test finished promise is not resolved when the animation ' +
|
||||||
|
'falls out finished state immediately');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
animation.finished.then(t.step_func(function() {
|
||||||
|
assert_unreached('Animation.finished should not be resolved');
|
||||||
|
}));
|
||||||
|
animation.currentTime = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 'Test finished promise is not resolved once the animation ' +
|
||||||
|
'falls out finished state even though the current finished ' +
|
||||||
|
'promise is generated soon after animation state became finished');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.id</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-id">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
assert_equals(animation.id, '', 'id for CSS Animation is initially empty');
|
||||||
|
animation.id = 'anim'
|
||||||
|
|
||||||
|
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
|
||||||
|
}, 'Animation.id for CSS Animations');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.oncancel</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-oncancel">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var finishedTimelineTime;
|
||||||
|
animation.finished.then().catch(function() {
|
||||||
|
finishedTimelineTime = animation.timeline.currentTime;
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.oncancel = t.step_func_done(function(event) {
|
||||||
|
assert_equals(event.currentTime, null,
|
||||||
|
'event.currentTime should be null');
|
||||||
|
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||||
|
'event.timelineTime should equal to the animation timeline ' +
|
||||||
|
'when finished promise is rejected');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.cancel();
|
||||||
|
}, 'oncancel event is fired when animation.cancel() is called.');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,122 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.onfinish</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-onfinish">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var finishedTimelineTime;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
finishedTimelineTime = animation.timeline.currentTime;
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.onfinish = t.step_func_done(function(event) {
|
||||||
|
assert_equals(event.currentTime, 0,
|
||||||
|
'event.currentTime should be zero');
|
||||||
|
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||||
|
'event.timelineTime should equal to the animation timeline ' +
|
||||||
|
'when finished promise is resolved');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
}, 'onfinish event is fired when the currentTime < 0 and ' +
|
||||||
|
'the playbackRate < 0');
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
var finishedTimelineTime;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
finishedTimelineTime = animation.timeline.currentTime;
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.onfinish = t.step_func_done(function(event) {
|
||||||
|
assert_equals(event.currentTime, 100 * MS_PER_SEC,
|
||||||
|
'event.currentTime should be the effect end');
|
||||||
|
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||||
|
'event.timelineTime should equal to the animation timeline ' +
|
||||||
|
'when finished promise is resolved');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
}, 'onfinish event is fired when the currentTime > 0 and ' +
|
||||||
|
'the playbackRate > 0');
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
var finishedTimelineTime;
|
||||||
|
animation.finished.then(function() {
|
||||||
|
finishedTimelineTime = animation.timeline.currentTime;
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.onfinish = t.step_func_done(function(event) {
|
||||||
|
assert_equals(event.currentTime, 100 * MS_PER_SEC,
|
||||||
|
'event.currentTime should be the effect end');
|
||||||
|
assert_equals(event.timelineTime, finishedTimelineTime,
|
||||||
|
'event.timelineTime should equal to the animation timeline ' +
|
||||||
|
'when finished promise is resolved');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.finish();
|
||||||
|
}, 'onfinish event is fired when animation.finish() is called');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
animation.onfinish = function(event) {
|
||||||
|
assert_unreached('onfinish event should not be fired');
|
||||||
|
};
|
||||||
|
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
animation.pause();
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
});
|
||||||
|
}, 'onfinish event is not fired when paused');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.onfinish = function(event) {
|
||||||
|
assert_unreached('onfinish event should not be fired');
|
||||||
|
};
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.playbackRate = 0;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
});
|
||||||
|
}, 'onfinish event is not fired when the playbackRate is zero');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.onfinish = function(event) {
|
||||||
|
assert_unreached('onfinish event should not be fired');
|
||||||
|
};
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC;
|
||||||
|
animation.currentTime = 100 * MS_PER_SEC / 2;
|
||||||
|
return waitForAnimationFrames(2);
|
||||||
|
});
|
||||||
|
}, 'onfinish event is not fired when the animation falls out ' +
|
||||||
|
'finished state immediately');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,99 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.pause()</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-pause">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||||
|
var previousCurrentTime = animation.currentTime;
|
||||||
|
|
||||||
|
return animation.ready.then(waitForAnimationFrames(1)).then(function() {
|
||||||
|
assert_true(animation.currentTime >= previousCurrentTime,
|
||||||
|
'currentTime is initially increasing');
|
||||||
|
animation.pause();
|
||||||
|
return animation.ready;
|
||||||
|
}).then(function() {
|
||||||
|
previousCurrentTime = animation.currentTime;
|
||||||
|
return waitForAnimationFrames(1);
|
||||||
|
}).then(function() {
|
||||||
|
assert_equals(animation.currentTime, previousCurrentTime,
|
||||||
|
'currentTime does not increase after calling pause()');
|
||||||
|
});
|
||||||
|
}, 'pause() a running animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||||
|
|
||||||
|
// Go to idle state then pause
|
||||||
|
animation.cancel();
|
||||||
|
animation.pause();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 0, 'currentTime is set to 0');
|
||||||
|
assert_equals(animation.startTime, null, 'startTime is not set');
|
||||||
|
assert_equals(animation.playState, 'pending', 'initially pause-pending');
|
||||||
|
|
||||||
|
// Check it still resolves as expected
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
assert_equals(animation.playState, 'paused',
|
||||||
|
'resolves to paused state asynchronously');
|
||||||
|
assert_equals(animation.currentTime, 0,
|
||||||
|
'keeps the initially set currentTime');
|
||||||
|
});
|
||||||
|
}, 'pause() from idle');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||||
|
animation.cancel();
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
animation.pause();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||||
|
'currentTime is set to the effect end');
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||||
|
'keeps the initially set currentTime');
|
||||||
|
});
|
||||||
|
}, 'pause() from idle with a negative playbackRate');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, {duration: 1000 * MS_PER_SEC,
|
||||||
|
iterations: Infinity});
|
||||||
|
animation.cancel();
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
|
||||||
|
assert_throws('InvalidStateError',
|
||||||
|
function () { animation.pause(); },
|
||||||
|
'Expect InvalidStateError exception on calling pause() ' +
|
||||||
|
'from idle with a negative playbackRate and ' +
|
||||||
|
'infinite-duration animation');
|
||||||
|
}, 'pause() from idle with a negative playbackRate and endless effect');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 1000 * MS_PER_SEC);
|
||||||
|
return animation.ready
|
||||||
|
.then(function(animation) {
|
||||||
|
animation.finish();
|
||||||
|
animation.pause();
|
||||||
|
return animation.ready;
|
||||||
|
}).then(function(animation) {
|
||||||
|
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
|
||||||
|
'currentTime after pausing finished animation');
|
||||||
|
});
|
||||||
|
}, 'pause() on a finished animation');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,97 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.ready</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-ready">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
var originalReadyPromise = animation.ready;
|
||||||
|
var pauseReadyPromise;
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
assert_equals(animation.ready, originalReadyPromise,
|
||||||
|
'Ready promise is the same object when playing completes');
|
||||||
|
animation.pause();
|
||||||
|
assert_not_equals(animation.ready, originalReadyPromise,
|
||||||
|
'A new ready promise is created when pausing');
|
||||||
|
pauseReadyPromise = animation.ready;
|
||||||
|
// Wait for the promise to fulfill since if we abort the pause the ready
|
||||||
|
// promise object is reused.
|
||||||
|
return animation.ready;
|
||||||
|
}).then(function() {
|
||||||
|
animation.play();
|
||||||
|
assert_not_equals(animation.ready, pauseReadyPromise,
|
||||||
|
'A new ready promise is created when playing');
|
||||||
|
});
|
||||||
|
}, 'A new ready promise is created when play()/pause() is called');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
var promiseBeforeCallingPlay = animation.ready;
|
||||||
|
animation.play();
|
||||||
|
assert_equals(animation.ready, promiseBeforeCallingPlay,
|
||||||
|
'Ready promise has same object identity after redundant call'
|
||||||
|
+ ' to play()');
|
||||||
|
});
|
||||||
|
}, 'Redundant calls to play() do not generate new ready promise objects');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
return animation.ready.then(function(resolvedAnimation) {
|
||||||
|
assert_equals(resolvedAnimation, animation,
|
||||||
|
'Object identity of Animation passed to Promise callback'
|
||||||
|
+ ' matches the Animation object owning the Promise');
|
||||||
|
});
|
||||||
|
}, 'The ready promise is fulfilled with its Animation');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
var retPromise = animation.ready.then(function() {
|
||||||
|
assert_unreached('ready promise was fulfilled');
|
||||||
|
}).catch(function(err) {
|
||||||
|
assert_equals(err.name, 'AbortError',
|
||||||
|
'ready promise is rejected with AbortError');
|
||||||
|
});
|
||||||
|
|
||||||
|
animation.cancel();
|
||||||
|
|
||||||
|
return retPromise;
|
||||||
|
}, 'ready promise is rejected when a pause-pending animation is cancelled by'
|
||||||
|
+ ' calling cancel()');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.pause();
|
||||||
|
// Set up listeners on pause-pending ready promise
|
||||||
|
var retPromise = animation.ready.then(function() {
|
||||||
|
assert_unreached('ready promise was fulfilled');
|
||||||
|
}).catch(function(err) {
|
||||||
|
assert_equals(err.name, 'AbortError',
|
||||||
|
'ready promise is rejected with AbortError');
|
||||||
|
});
|
||||||
|
animation.cancel();
|
||||||
|
return retPromise;
|
||||||
|
});
|
||||||
|
}, 'ready promise is rejected when a pause-pending animation is cancelled by'
|
||||||
|
+ ' calling cancel()');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,150 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Animation.reverse()</title>
|
||||||
|
<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-reverse">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="../testcommon.js"></script>
|
||||||
|
<link rel="stylesheet" href="/resources/testharness.css">
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||||
|
iterations: Infinity});
|
||||||
|
|
||||||
|
// Wait a frame because if currentTime is still 0 when we call
|
||||||
|
// reverse(), it will throw (per spec).
|
||||||
|
return animation.ready.then(waitForAnimationFrames(1)).then(function() {
|
||||||
|
assert_greater_than_equal(animation.currentTime, 0,
|
||||||
|
'currentTime expected to be greater than 0, one frame after starting');
|
||||||
|
animation.currentTime = 50 * MS_PER_SEC;
|
||||||
|
var previousPlaybackRate = animation.playbackRate;
|
||||||
|
animation.reverse();
|
||||||
|
assert_equals(animation.playbackRate, -previousPlaybackRate,
|
||||||
|
'playbackRate should be inverted');
|
||||||
|
});
|
||||||
|
}, 'reverse() inverts playbackRate');
|
||||||
|
|
||||||
|
promise_test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||||
|
iterations: Infinity});
|
||||||
|
animation.currentTime = 50 * MS_PER_SEC;
|
||||||
|
animation.pause();
|
||||||
|
|
||||||
|
return animation.ready.then(function() {
|
||||||
|
animation.reverse();
|
||||||
|
return animation.ready;
|
||||||
|
}).then(function() {
|
||||||
|
assert_equals(animation.playState, 'running',
|
||||||
|
'Animation.playState should be "running" after reverse()');
|
||||||
|
});
|
||||||
|
}, 'reverse() starts to play when pausing animation');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.currentTime = 50 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 50 * MS_PER_SEC,
|
||||||
|
'reverse() should not change the currentTime ' +
|
||||||
|
'if the currentTime is in the middle of animation duration');
|
||||||
|
}, 'reverse() maintains the same currentTime');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.currentTime = 200 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||||
|
'reverse() should start playing from the animation effect end ' +
|
||||||
|
'if the playbackRate > 0 and the currentTime > effect end');
|
||||||
|
}, 'reverse() when playbackRate > 0 and currentTime > effect end');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
|
||||||
|
animation.currentTime = -200 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
|
||||||
|
'reverse() should start playing from the animation effect end ' +
|
||||||
|
'if the playbackRate > 0 and the currentTime < 0');
|
||||||
|
}, 'reverse() when playbackRate > 0 and currentTime < 0');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
animation.currentTime = -200 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 0,
|
||||||
|
'reverse() should start playing from the start of animation time ' +
|
||||||
|
'if the playbackRate < 0 and the currentTime < 0');
|
||||||
|
}, 'reverse() when playbackRate < 0 and currentTime < 0');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
animation.currentTime = 200 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 0,
|
||||||
|
'reverse() should start playing from the start of animation time ' +
|
||||||
|
'if the playbackRate < 0 and the currentTime > effect end');
|
||||||
|
}, 'reverse() when playbackRate < 0 and currentTime > effect end');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||||
|
iterations: Infinity});
|
||||||
|
animation.currentTime = -200 * MS_PER_SEC;
|
||||||
|
|
||||||
|
assert_throws('InvalidStateError',
|
||||||
|
function () { animation.reverse(); },
|
||||||
|
'reverse() should throw InvalidStateError ' +
|
||||||
|
'if the playbackRate > 0 and the currentTime < 0 ' +
|
||||||
|
'and the target effect is positive infinity');
|
||||||
|
}, 'reverse() when playbackRate > 0 and currentTime < 0 ' +
|
||||||
|
'and the target effect end is positive infinity');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
|
||||||
|
iterations: Infinity});
|
||||||
|
animation.playbackRate = -1;
|
||||||
|
animation.currentTime = -200 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.currentTime, 0,
|
||||||
|
'reverse() should start playing from the start of animation time ' +
|
||||||
|
'if the playbackRate < 0 and the currentTime < 0 ' +
|
||||||
|
'and the target effect is positive infinity');
|
||||||
|
}, 'reverse() when playbackRate < 0 and currentTime < 0 ' +
|
||||||
|
'and the target effect end is positive infinity');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var animation = div.animate({}, 100 * MS_PER_SEC);
|
||||||
|
animation.playbackRate = 0;
|
||||||
|
animation.currentTime = 50 * MS_PER_SEC;
|
||||||
|
animation.reverse();
|
||||||
|
|
||||||
|
assert_equals(animation.playbackRate, 0,
|
||||||
|
'reverse() should preserve playbackRate if the playbackRate == 0');
|
||||||
|
assert_equals(animation.currentTime, 50 * MS_PER_SEC,
|
||||||
|
'reverse() should not affect the currentTime if the playbackRate == 0');
|
||||||
|
t.done();
|
||||||
|
}, 'reverse() when playbackRate == 0');
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -37,17 +37,6 @@ function assert_frame_lists_equal(a, b) {
|
||||||
|
|
||||||
var gEmptyKeyframeListTests = [
|
var gEmptyKeyframeListTests = [
|
||||||
[],
|
[],
|
||||||
[{}],
|
|
||||||
[{ easing: "ease-in" }],
|
|
||||||
[{ unknown: "unknown" }, { unknown: "unknown" }],
|
|
||||||
[{ color: "invalid" }, { color: "invalid" }],
|
|
||||||
{ easing: "ease-in" },
|
|
||||||
{ unknown: "unknown" },
|
|
||||||
{ unknown: [] },
|
|
||||||
{ unknown: ["unknown"] },
|
|
||||||
{ unknown: ["unknown", "unknown"] },
|
|
||||||
{ animationName: ["none", "abc"] },
|
|
||||||
{ color: [] },
|
|
||||||
null,
|
null,
|
||||||
undefined,
|
undefined,
|
||||||
];
|
];
|
||||||
|
@ -79,7 +68,7 @@ test(function(t) {
|
||||||
"resulting easing for '" + easing + "'");
|
"resulting easing for '" + easing + "'");
|
||||||
});
|
});
|
||||||
}, "easing values are parsed correctly when passed to the " +
|
}, "easing values are parsed correctly when passed to the " +
|
||||||
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
|
"KeyframeEffectReadOnly constructor in a property-indexed keyframe");
|
||||||
|
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
gEasingValueTests.forEach(function(subtest) {
|
gEasingValueTests.forEach(function(subtest) {
|
||||||
|
@ -93,7 +82,7 @@ test(function(t) {
|
||||||
"resulting easing for '" + easing + "'");
|
"resulting easing for '" + easing + "'");
|
||||||
});
|
});
|
||||||
}, "easing values are parsed correctly when passed to the " +
|
}, "easing values are parsed correctly when passed to the " +
|
||||||
"KeyframeEffectReadOnly constructor in Keyframe");
|
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||||
|
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
gEasingValueTests.forEach(function(subtest) {
|
gEasingValueTests.forEach(function(subtest) {
|
||||||
|
@ -135,7 +124,7 @@ test(function(t) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, "composite values are parsed correctly when passed to the " +
|
}, "composite values are parsed correctly when passed to the " +
|
||||||
"KeyframeEffectReadOnly constructor in PropertyIndexedKeyframes");
|
"KeyframeEffectReadOnly constructor in property-indexed keyframes");
|
||||||
|
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
var getFrames = function(composite) {
|
var getFrames = function(composite) {
|
||||||
|
@ -155,7 +144,7 @@ test(function(t) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, "composite values are parsed correctly when passed to the " +
|
}, "composite values are parsed correctly when passed to the " +
|
||||||
"KeyframeEffectReadOnly constructor in Keyframe");
|
"KeyframeEffectReadOnly constructor in regular keyframes");
|
||||||
|
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
gGoodOptionsCompositeValueTests.forEach(function(composite) {
|
gGoodOptionsCompositeValueTests.forEach(function(composite) {
|
||||||
|
@ -176,79 +165,119 @@ test(function(t) {
|
||||||
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
|
"KeyframeEffectReadOnly constructor in KeyframeTimingOptions");
|
||||||
|
|
||||||
var gPropertyIndexedKeyframesTests = [
|
var gPropertyIndexedKeyframesTests = [
|
||||||
{ desc: "a one property two value PropertyIndexedKeyframes specification",
|
{ desc: "a one property two value property-indexed keyframes specification",
|
||||||
input: { left: ["10px", "20px"] },
|
input: { left: ["10px", "20px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
|
left: "10px" },
|
||||||
{ desc: "a one shorthand property two value PropertyIndexedKeyframes specification",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
left: "20px" }] },
|
||||||
|
{ desc: "a one shorthand property two value property-indexed keyframes"
|
||||||
|
+ " specification",
|
||||||
input: { margin: ["10px", "10px 20px 30px 40px"] },
|
input: { margin: ["10px", "10px 20px 30px 40px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "10px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
|
margin: "10px" },
|
||||||
{ desc: "a two property (one shorthand and one of its longhand components) two value PropertyIndexedKeyframes specification",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
margin: "10px 20px 30px 40px" }] },
|
||||||
|
{ desc: "a two property (one shorthand and one of its longhand components)"
|
||||||
|
+ " two value property-indexed keyframes specification",
|
||||||
input: { marginTop: ["50px", "60px"],
|
input: { marginTop: ["50px", "60px"],
|
||||||
margin: ["10px", "10px 20px 30px 40px"] },
|
margin: ["10px", "10px 20px 30px 40px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "50px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "60px", marginRight: "20px", marginBottom: "30px", marginLeft: "40px" }] },
|
marginTop: "50px", margin: "10px" },
|
||||||
{ desc: "a two property two value PropertyIndexedKeyframes specification",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
marginTop: "60px", margin: "10px 20px 30px 40px" }] },
|
||||||
|
{ desc: "a two property two value property-indexed keyframes specification",
|
||||||
input: { left: ["10px", "20px"],
|
input: { left: ["10px", "20px"],
|
||||||
top: ["30px", "40px"] },
|
top: ["30px", "40px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
|
left: "10px", top: "30px" },
|
||||||
{ desc: "a two property PropertyIndexedKeyframes specification with different numbers of values",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
left: "20px", top: "40px" }] },
|
||||||
|
{ desc: "a two property property-indexed keyframes specification with"
|
||||||
|
+ " different numbers of values",
|
||||||
input: { left: ["10px", "20px", "30px"],
|
input: { left: ["10px", "20px", "30px"],
|
||||||
top: ["40px", "50px"] },
|
top: ["40px", "50px"] },
|
||||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px", top: "40px" },
|
output: [{ offset: null, computedOffset: 0.0, easing: "linear",
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
|
left: "10px", top: "40px" },
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "30px", top: "50px" }] },
|
{ offset: null, computedOffset: 0.5, easing: "linear",
|
||||||
{ desc: "a PropertyIndexedKeyframes specification with an invalid value",
|
left: "20px" },
|
||||||
|
{ offset: null, computedOffset: 1.0, easing: "linear",
|
||||||
|
left: "30px", top: "50px" }] },
|
||||||
|
{ desc: "a property-indexed keyframes specification with an invalid value",
|
||||||
input: { left: ["10px", "20px", "30px", "40px", "50px"],
|
input: { left: ["10px", "20px", "30px", "40px", "50px"],
|
||||||
top: ["15px", "25px", "invalid", "45px", "55px"] },
|
top: ["15px", "25px", "invalid", "45px", "55px"] },
|
||||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "15px" },
|
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
|
||||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px", top: "25px" },
|
left: "10px", top: "15px" },
|
||||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
{ offset: null, computedOffset: 0.25, easing: "linear",
|
||||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px", top: "45px" },
|
left: "20px", top: "25px" },
|
||||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px", top: "55px" }] },
|
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||||
{ desc: "a one property two value PropertyIndexedKeyframes specification that needs to stringify its values",
|
left: "30px", top: "invalid" },
|
||||||
|
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||||
|
left: "40px", top: "45px" },
|
||||||
|
{ offset: null, computedOffset: 1.00, easing: "linear",
|
||||||
|
left: "50px", top: "55px" }] },
|
||||||
|
{ desc: "a one property two value property-indexed keyframes specification"
|
||||||
|
+ " that needs to stringify its values",
|
||||||
input: { opacity: [0, 1] },
|
input: { opacity: [0, 1] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
|
opacity: "0" },
|
||||||
{ desc: "a one property one value PropertyIndexedKeyframes specification",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
opacity: "1" }] },
|
||||||
|
{ desc: "a one property one value property-indexed keyframes specification",
|
||||||
input: { left: ["10px"] },
|
input: { left: ["10px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
left: "10px" }] },
|
||||||
{ desc: "a one property one non-array value PropertyIndexedKeyframes specification",
|
{ desc: "a one property one non-array value property-indexed keyframes"
|
||||||
|
+ " specification",
|
||||||
input: { left: "10px" },
|
input: { left: "10px" },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
output: [{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
left: "10px" }] },
|
||||||
{ desc: "a one property two value PropertyIndexedKeyframes specification where the first value is invalid",
|
{ desc: "a one property two value property-indexed keyframes specification"
|
||||||
|
+ " where the first value is invalid",
|
||||||
input: { left: ["invalid", "10px"] },
|
input: { left: ["invalid", "10px"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "10px" }] },
|
left: "invalid" },
|
||||||
{ desc: "a one property two value PropertyIndexedKeyframes specification where the second value is invalid",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
left: "10px" }] },
|
||||||
|
{ desc: "a one property two value property-indexed keyframes specification"
|
||||||
|
+ " where the second value is invalid",
|
||||||
input: { left: ["10px", "invalid"] },
|
input: { left: ["10px", "invalid"] },
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
output: [{ offset: null, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear" }] },
|
left: "10px" },
|
||||||
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the first Keyframe",
|
{ offset: null, computedOffset: 1, easing: "linear",
|
||||||
|
left: "invalid" }] },
|
||||||
|
{ desc: "a two property property-indexed keyframes specification where one"
|
||||||
|
+ " property is missing from the first keyframe",
|
||||||
input: [{ offset: 0, left: "10px" },
|
input: [{ offset: 0, left: "10px" },
|
||||||
{ offset: 1, left: "20px", top: "30px" }],
|
{ offset: 1, left: "20px", top: "30px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "30px" }] },
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
{ desc: "a two property PropertyIndexedKeyframes specification where one property is missing from the last Keyframe",
|
left: "20px", top: "30px" }] },
|
||||||
|
{ desc: "a two property property-indexed keyframes specification where one"
|
||||||
|
+ " property is missing from the last keyframe",
|
||||||
input: [{ offset: 0, left: "10px", top: "20px" },
|
input: [{ offset: 0, left: "10px", top: "20px" },
|
||||||
{ offset: 1, left: "30px" }],
|
{ offset: 1, left: "30px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" , top: "20px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "30px" }] },
|
left: "10px" , top: "20px" },
|
||||||
{ desc: "a PropertyIndexedKeyframes specification with repeated values at offset 0 with different easings",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
|
left: "30px" }] },
|
||||||
|
{ desc: "a property-indexed keyframes specification with repeated values"
|
||||||
|
+ " at offset 0 with different easings",
|
||||||
input: [{ offset: 0.0, left: "100px", easing: "ease" },
|
input: [{ offset: 0.0, left: "100px", easing: "ease" },
|
||||||
{ offset: 0.0, left: "200px", easing: "ease" },
|
{ offset: 0.0, left: "200px", easing: "ease" },
|
||||||
{ offset: 0.5, left: "300px", easing: "linear" },
|
{ offset: 0.5, left: "300px", easing: "linear" },
|
||||||
{ offset: 1.0, left: "400px", easing: "ease-out" },
|
{ offset: 1.0, left: "400px", easing: "ease-out" },
|
||||||
{ offset: 1.0, left: "500px", easing: "step-end" }],
|
{ offset: 1.0, left: "500px", easing: "step-end" }],
|
||||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "100px" },
|
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||||
{ offset: 0.0, computedOffset: 0.0, easing: "ease", left: "200px" },
|
left: "100px" },
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "300px" },
|
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out", left: "400px" },
|
left: "200px" },
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "500px" }] },
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
|
left: "300px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "ease-out",
|
||||||
|
left: "400px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||||
|
left: "500px" }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
gPropertyIndexedKeyframesTests.forEach(function(subtest) {
|
||||||
|
@ -282,41 +311,56 @@ test(function(t) {
|
||||||
});
|
});
|
||||||
new KeyframeEffectReadOnly(target, [kf1, kf2]);
|
new KeyframeEffectReadOnly(target, [kf1, kf2]);
|
||||||
assert_array_equals(actualOrder, expectedOrder, "property access order");
|
assert_array_equals(actualOrder, expectedOrder, "property access order");
|
||||||
}, "the KeyframeEffectReadOnly constructor reads Keyframe properties in the " +
|
}, "the KeyframeEffectReadOnly constructor reads keyframe properties in the " +
|
||||||
"expected order");
|
"expected order");
|
||||||
|
|
||||||
var gKeyframeSequenceTests = [
|
var gKeyframeSequenceTests = [
|
||||||
{ desc: "a one property two Keyframe sequence",
|
{ desc: "a one property two keyframe sequence",
|
||||||
input: [{ offset: 0, left: "10px" },
|
input: [{ offset: 0, left: "10px" },
|
||||||
{ offset: 1, left: "20px" }],
|
{ offset: 1, left: "20px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }] },
|
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px" }]
|
||||||
{ desc: "a two property two Keyframe sequence",
|
},
|
||||||
|
{ desc: "a two property two keyframe sequence",
|
||||||
input: [{ offset: 0, left: "10px", top: "30px" },
|
input: [{ offset: 0, left: "10px", top: "30px" },
|
||||||
{ offset: 1, left: "20px", top: "40px" }],
|
{ offset: 1, left: "20px", top: "40px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "30px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "20px", top: "40px" }] },
|
left: "10px", top: "30px" },
|
||||||
{ desc: "a one shorthand property two Keyframe sequence",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
|
left: "20px", top: "40px" }] },
|
||||||
|
{ desc: "a one shorthand property two keyframe sequence",
|
||||||
input: [{ offset: 0, margin: "10px" },
|
input: [{ offset: 0, margin: "10px" },
|
||||||
{ offset: 1, margin: "20px 30px 40px 50px" }],
|
{ offset: 1, margin: "20px 30px 40px 50px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "10px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "20px", marginRight: "30px", marginBottom: "40px", marginLeft: "50px" }] },
|
margin: "10px" },
|
||||||
{ desc: "a two property (a shorthand and one of its component longhands) two Keyframe sequence",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
|
margin: "20px 30px 40px 50px" }] },
|
||||||
|
{ desc: "a two property (a shorthand and one of its component longhands)"
|
||||||
|
+ " two keyframe sequence",
|
||||||
input: [{ offset: 0, margin: "10px", marginTop: "20px" },
|
input: [{ offset: 0, margin: "10px", marginTop: "20px" },
|
||||||
{ offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
|
{ offset: 1, marginTop: "70px", margin: "30px 40px 50px 60px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginTop: "20px", marginRight: "10px", marginBottom: "10px", marginLeft: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginTop: "70px", marginRight: "40px", marginBottom: "50px", marginLeft: "60px" }] },
|
margin: "10px", marginTop: "20px" },
|
||||||
{ desc: "a Keyframe sequence with duplicate values for a given interior offset",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
|
marginTop: "70px", margin: "30px 40px 50px 60px" }] },
|
||||||
|
{ desc: "a keyframe sequence with duplicate values for a given interior"
|
||||||
|
+ " offset",
|
||||||
input: [{ offset: 0.0, left: "10px" },
|
input: [{ offset: 0.0, left: "10px" },
|
||||||
{ offset: 0.5, left: "20px" },
|
{ offset: 0.5, left: "20px" },
|
||||||
{ offset: 0.5, left: "30px" },
|
{ offset: 0.5, left: "30px" },
|
||||||
{ offset: 0.5, left: "40px" },
|
{ offset: 0.5, left: "40px" },
|
||||||
{ offset: 1.0, left: "50px" }],
|
{ offset: 1.0, left: "50px" }],
|
||||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", left: "10px" },
|
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "20px" },
|
left: "10px" },
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", left: "40px" },
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", left: "50px" }] },
|
left: "20px" },
|
||||||
{ desc: "a Keyframe sequence with duplicate values for offsets 0 and 1",
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
|
left: "30px" },
|
||||||
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
|
left: "40px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||||
|
left: "50px" }] },
|
||||||
|
{ desc: "a keyframe sequence with duplicate values for offsets 0 and 1",
|
||||||
input: [{ offset: 0, left: "10px" },
|
input: [{ offset: 0, left: "10px" },
|
||||||
{ offset: 0, left: "20px" },
|
{ offset: 0, left: "20px" },
|
||||||
{ offset: 0, left: "30px" },
|
{ offset: 0, left: "30px" },
|
||||||
|
@ -324,50 +368,72 @@ var gKeyframeSequenceTests = [
|
||||||
{ offset: 1, left: "50px" },
|
{ offset: 1, left: "50px" },
|
||||||
{ offset: 1, left: "60px" }],
|
{ offset: 1, left: "60px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||||
|
{ offset: 0, computedOffset: 0, easing: "linear", left: "20px" },
|
||||||
{ offset: 0, computedOffset: 0, easing: "linear", left: "30px" },
|
{ offset: 0, computedOffset: 0, easing: "linear", left: "30px" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" },
|
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }] },
|
{ offset: 1, computedOffset: 1, easing: "linear", left: "50px" },
|
||||||
{ desc: "a two property four Keyframe sequence",
|
{ offset: 1, computedOffset: 1, easing: "linear", left: "60px" }]
|
||||||
|
},
|
||||||
|
{ desc: "a two property four keyframe sequence",
|
||||||
input: [{ offset: 0, left: "10px" },
|
input: [{ offset: 0, left: "10px" },
|
||||||
{ offset: 0, top: "20px" },
|
{ offset: 0, top: "20px" },
|
||||||
{ offset: 1, top: "30px" },
|
{ offset: 1, top: "30px" },
|
||||||
{ offset: 1, left: "40px" }],
|
{ offset: 1, left: "40px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px", top: "20px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear", left: "10px" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px", top: "30px" }] },
|
{ offset: 0, computedOffset: 0, easing: "linear", top: "20px" },
|
||||||
{ desc: "a one property Keyframe sequence with some omitted offsets",
|
{ offset: 1, computedOffset: 1, easing: "linear", top: "30px" },
|
||||||
|
{ offset: 1, computedOffset: 1, easing: "linear", left: "40px" }]
|
||||||
|
},
|
||||||
|
{ desc: "a one property keyframe sequence with some omitted offsets",
|
||||||
input: [{ offset: 0.00, left: "10px" },
|
input: [{ offset: 0.00, left: "10px" },
|
||||||
{ offset: 0.25, left: "20px" },
|
{ offset: 0.25, left: "20px" },
|
||||||
{ left: "30px" },
|
{ left: "30px" },
|
||||||
{ left: "40px" },
|
{ left: "40px" },
|
||||||
{ offset: 1.00, left: "50px" }],
|
{ offset: 1.00, left: "50px" }],
|
||||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
|
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
|
||||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
|
left: "10px" },
|
||||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
|
||||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
|
left: "20px" },
|
||||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
|
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||||
{ desc: "a two property Keyframe sequence with some omitted offsets",
|
left: "30px" },
|
||||||
|
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||||
|
left: "40px" },
|
||||||
|
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
|
||||||
|
left: "50px" }] },
|
||||||
|
{ desc: "a two property keyframe sequence with some omitted offsets",
|
||||||
input: [{ offset: 0.00, left: "10px", top: "20px" },
|
input: [{ offset: 0.00, left: "10px", top: "20px" },
|
||||||
{ offset: 0.25, left: "30px" },
|
{ offset: 0.25, left: "30px" },
|
||||||
{ left: "40px" },
|
{ left: "40px" },
|
||||||
{ left: "50px", top: "60px" },
|
{ left: "50px", top: "60px" },
|
||||||
{ offset: 1.00, left: "70px", top: "80px" }],
|
{ offset: 1.00, left: "70px", top: "80px" }],
|
||||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px", top: "20px" },
|
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear",
|
||||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "30px" },
|
left: "10px", top: "20px" },
|
||||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "40px" },
|
{ offset: 0.25, computedOffset: 0.25, easing: "linear",
|
||||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "50px", top: "60px" },
|
left: "30px" },
|
||||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "70px", top: "80px" }] },
|
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||||
{ desc: "a one property Keyframe sequence with all omitted offsets",
|
left: "40px" },
|
||||||
|
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||||
|
left: "50px", top: "60px" },
|
||||||
|
{ offset: 1.00, computedOffset: 1.00, easing: "linear",
|
||||||
|
left: "70px", top: "80px" }] },
|
||||||
|
{ desc: "a one property keyframe sequence with all omitted offsets",
|
||||||
input: [{ left: "10px" },
|
input: [{ left: "10px" },
|
||||||
{ left: "20px" },
|
{ left: "20px" },
|
||||||
{ left: "30px" },
|
{ left: "30px" },
|
||||||
{ left: "40px" },
|
{ left: "40px" },
|
||||||
{ left: "50px" }],
|
{ left: "50px" }],
|
||||||
output: [{ offset: 0.00, computedOffset: 0.00, easing: "linear", left: "10px" },
|
output: [{ offset: null, computedOffset: 0.00, easing: "linear",
|
||||||
{ offset: 0.25, computedOffset: 0.25, easing: "linear", left: "20px" },
|
left: "10px" },
|
||||||
{ offset: 0.50, computedOffset: 0.50, easing: "linear", left: "30px" },
|
{ offset: null, computedOffset: 0.25, easing: "linear",
|
||||||
{ offset: 0.75, computedOffset: 0.75, easing: "linear", left: "40px" },
|
left: "20px" },
|
||||||
{ offset: 1.00, computedOffset: 1.00, easing: "linear", left: "50px" }] },
|
{ offset: null, computedOffset: 0.50, easing: "linear",
|
||||||
{ desc: "a Keyframe sequence with different easing values, but the same easing value for a given offset",
|
left: "30px" },
|
||||||
|
{ offset: null, computedOffset: 0.75, easing: "linear",
|
||||||
|
left: "40px" },
|
||||||
|
{ offset: null, computedOffset: 1.00, easing: "linear",
|
||||||
|
left: "50px" }] },
|
||||||
|
{ desc: "a keyframe sequence with different easing values, but the same"
|
||||||
|
+ " easing value for a given offset",
|
||||||
input: [{ offset: 0.0, easing: "ease", left: "10px"},
|
input: [{ offset: 0.0, easing: "ease", left: "10px"},
|
||||||
{ offset: 0.0, easing: "ease", top: "20px"},
|
{ offset: 0.0, easing: "ease", top: "20px"},
|
||||||
{ offset: 0.5, easing: "linear", left: "30px" },
|
{ offset: 0.5, easing: "linear", left: "30px" },
|
||||||
|
@ -375,62 +441,79 @@ var gKeyframeSequenceTests = [
|
||||||
{ offset: 1.0, easing: "step-end", left: "50px" },
|
{ offset: 1.0, easing: "step-end", left: "50px" },
|
||||||
{ offset: 1.0, easing: "step-end", top: "60px" }],
|
{ offset: 1.0, easing: "step-end", top: "60px" }],
|
||||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
output: [{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||||
left: "10px", top: "20px" },
|
left: "10px" },
|
||||||
|
{ offset: 0.0, computedOffset: 0.0, easing: "ease",
|
||||||
|
top: "20px" },
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
left: "30px", top: "40px" },
|
left: "30px" },
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
{ offset: 0.5, computedOffset: 0.5, easing: "linear",
|
||||||
left: "50px", top: "60px" }] },
|
top: "40px" },
|
||||||
{ desc: "a Keyframe sequence with different composite values, but the same composite value for a given offset",
|
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||||
|
left: "50px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "step-end",
|
||||||
|
top: "60px" }] },
|
||||||
|
{ desc: "a keyframe sequence with different composite values, but the"
|
||||||
|
+ " same composite value for a given offset",
|
||||||
input: [{ offset: 0.0, composite: "replace", left: "10px" },
|
input: [{ offset: 0.0, composite: "replace", left: "10px" },
|
||||||
{ offset: 0.0, composite: "replace", top: "20px" },
|
{ offset: 0.0, composite: "replace", top: "20px" },
|
||||||
{ offset: 0.5, composite: "add", left: "30px" },
|
{ offset: 0.5, composite: "add", left: "30px" },
|
||||||
{ offset: 0.5, composite: "add", top: "40px" },
|
{ offset: 0.5, composite: "add", top: "40px" },
|
||||||
{ offset: 1.0, composite: "replace", left: "50px" },
|
{ offset: 1.0, composite: "replace", left: "50px" },
|
||||||
{ offset: 1.0, composite: "replace", top: "60px" }],
|
{ offset: 1.0, composite: "replace", top: "60px" }],
|
||||||
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear", composite: "replace", left: "10px", top: "20px" },
|
output: [{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||||
{ offset: 0.5, computedOffset: 0.5, easing: "linear", composite: "add", left: "30px", top: "40px" },
|
composite: "replace", left: "10px" },
|
||||||
{ offset: 1.0, computedOffset: 1.0, easing: "linear", composite: "replace", left: "50px", top: "60px" }] },
|
{ offset: 0.0, computedOffset: 0.0, easing: "linear",
|
||||||
{ desc: "a one property two Keyframe sequence that needs to stringify its values",
|
composite: "replace", top: "20px" },
|
||||||
|
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
|
||||||
|
composite: "add", left: "30px" },
|
||||||
|
{ offset: 0.5, computedOffset: 0.0, easing: "linear",
|
||||||
|
composite: "add", top: "40px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||||
|
composite: "replace", left: "50px" },
|
||||||
|
{ offset: 1.0, computedOffset: 1.0, easing: "linear",
|
||||||
|
composite: "replace", top: "60px" }] },
|
||||||
|
{ desc: "a one property two keyframe sequence that needs to stringify"
|
||||||
|
+ " its values",
|
||||||
input: [{ offset: 0, opacity: 0 },
|
input: [{ offset: 0, opacity: 0 },
|
||||||
{ offset: 1, opacity: 1 }],
|
{ offset: 1, opacity: 1 }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear", opacity: "0" },
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }] },
|
{ offset: 1, computedOffset: 1, easing: "linear", opacity: "1" }]
|
||||||
{ desc: "a Keyframe sequence where shorthand precedes longhand",
|
},
|
||||||
|
{ desc: "a keyframe sequence where shorthand precedes longhand",
|
||||||
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
|
input: [{ offset: 0, margin: "10px", marginRight: "20px" },
|
||||||
{ offset: 1, margin: "30px" }],
|
{ offset: 1, margin: "30px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
|
margin: "10px", marginRight: "20px" },
|
||||||
{ desc: "a Keyframe sequence where longhand precedes shorthand",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
|
margin: "30px" }] },
|
||||||
|
{ desc: "a keyframe sequence where longhand precedes shorthand",
|
||||||
input: [{ offset: 0, marginRight: "20px", margin: "10px" },
|
input: [{ offset: 0, marginRight: "20px", margin: "10px" },
|
||||||
{ offset: 1, margin: "30px" }],
|
{ offset: 1, margin: "30px" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear", marginBottom: "10px", marginLeft: "10px", marginRight: "20px", marginTop: "10px" },
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear", marginBottom: "30px", marginLeft: "30px", marginRight: "30px", marginTop: "30px" }] },
|
marginRight: "20px", margin: "10px" },
|
||||||
{ desc: "a Keyframe sequence where lesser shorthand precedes greater shorthand",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
input: [{ offset: 0, borderLeft: "1px solid rgb(1, 2, 3)", border: "2px dotted rgb(4, 5, 6)" },
|
margin: "30px" }] },
|
||||||
|
{ desc: "a keyframe sequence where lesser shorthand precedes greater"
|
||||||
|
+ " shorthand",
|
||||||
|
input: [{ offset: 0,
|
||||||
|
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||||
|
border: "2px dotted rgb(4, 5, 6)" },
|
||||||
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
|
borderLeft: "1px solid rgb(1, 2, 3)",
|
||||||
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
|
border: "2px dotted rgb(4, 5, 6)" },
|
||||||
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
|
|
||||||
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
|
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
|
border: "3px dashed rgb(7, 8, 9)" }] },
|
||||||
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
|
{ desc: "a keyframe sequence where greater shorthand precedes lesser"
|
||||||
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
|
+ " shorthand",
|
||||||
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
|
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)",
|
||||||
{ desc: "a Keyframe sequence where greater shorthand precedes lesser shorthand",
|
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||||
input: [{ offset: 0, border: "2px dotted rgb(4, 5, 6)", borderLeft: "1px solid rgb(1, 2, 3)" },
|
|
||||||
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
{ offset: 1, border: "3px dashed rgb(7, 8, 9)" }],
|
||||||
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
output: [{ offset: 0, computedOffset: 0, easing: "linear",
|
||||||
borderBottomColor: "rgb(4, 5, 6)", borderBottomWidth: "2px",
|
border: "2px dotted rgb(4, 5, 6)",
|
||||||
borderLeftColor: "rgb(1, 2, 3)", borderLeftWidth: "1px",
|
borderLeft: "1px solid rgb(1, 2, 3)" },
|
||||||
borderRightColor: "rgb(4, 5, 6)", borderRightWidth: "2px",
|
|
||||||
borderTopColor: "rgb(4, 5, 6)", borderTopWidth: "2px" },
|
|
||||||
{ offset: 1, computedOffset: 1, easing: "linear",
|
{ offset: 1, computedOffset: 1, easing: "linear",
|
||||||
borderBottomColor: "rgb(7, 8, 9)", borderBottomWidth: "3px",
|
border: "3px dashed rgb(7, 8, 9)" }] },
|
||||||
borderLeftColor: "rgb(7, 8, 9)", borderLeftWidth: "3px",
|
|
||||||
borderRightColor: "rgb(7, 8, 9)", borderRightWidth: "3px",
|
|
||||||
borderTopColor: "rgb(7, 8, 9)", borderTopWidth: "3px" }] },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
gKeyframeSequenceTests.forEach(function(subtest) {
|
gKeyframeSequenceTests.forEach(function(subtest) {
|
||||||
|
@ -467,7 +550,7 @@ gInvalidEasingInKeyframeSequenceTests.forEach(function(subtest) {
|
||||||
assert_throws(new TypeError, function() {
|
assert_throws(new TypeError, function() {
|
||||||
new KeyframeEffectReadOnly(target, subtest.input);
|
new KeyframeEffectReadOnly(target, subtest.input);
|
||||||
});
|
});
|
||||||
}, "Invalid easing [" + subtest.desc + "] in KeyframeSequence " +
|
}, "Invalid easing [" + subtest.desc + "] in keyframe sequence " +
|
||||||
"should be thrown");
|
"should be thrown");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<script src="/resources/testharness.js"></script>
|
<script src="/resources/testharness.js"></script>
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
<script src="../testcommon.js"></script>
|
<script src="../testcommon.js"></script>
|
||||||
|
<script src="../resources/effect-easing-tests.js"></script>
|
||||||
<body>
|
<body>
|
||||||
<div id="log"></div>
|
<div id="log"></div>
|
||||||
<div id="target"></div>
|
<div id="target"></div>
|
||||||
|
@ -22,54 +23,6 @@ function assert_style_left_at(animation, time, easingFunction) {
|
||||||
easingFunction(portion) * 100 + ' at ' + time + 'ms');
|
easingFunction(portion) * 100 + ' at ' + time + 'ms');
|
||||||
}
|
}
|
||||||
|
|
||||||
var gEffectEasingTests = [
|
|
||||||
{
|
|
||||||
desc: 'steps(start) function',
|
|
||||||
easing: 'steps(2, start)',
|
|
||||||
easingFunction: stepStart(2)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'steps(end) function',
|
|
||||||
easing: 'steps(2, end)',
|
|
||||||
easingFunction: stepEnd(2)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'linear function',
|
|
||||||
easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0)
|
|
||||||
easingFunction: cubicBezier(0, 0, 1.0, 1.0)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'ease function',
|
|
||||||
easing: 'ease', // cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
|
||||||
easingFunction: cubicBezier(0.25, 0.1, 0.25, 1.0)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'ease-in function',
|
|
||||||
easing: 'ease-in', // cubic-bezier(0.42, 0, 1.0, 1.0)
|
|
||||||
easingFunction: cubicBezier(0.42, 0, 1.0, 1.0)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'ease-in-out function',
|
|
||||||
easing: 'ease-in-out', // cubic-bezier(0.42, 0, 0.58, 1.0)
|
|
||||||
easingFunction: cubicBezier(0.42, 0, 0.58, 1.0)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'ease-out function',
|
|
||||||
easing: 'ease-out', // cubic-bezier(0, 0, 0.58, 1.0)
|
|
||||||
easingFunction: cubicBezier(0, 0, 0.58, 1.0)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'easing function which produces values greater than 1',
|
|
||||||
easing: 'cubic-bezier(0, 1.5, 1, 1.5)',
|
|
||||||
easingFunction: cubicBezier(0, 1.5, 1, 1.5)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
desc: 'easing function which produces negative values',
|
|
||||||
easing: 'cubic-bezier(0, -0.5 ,1, -0.5)',
|
|
||||||
easingFunction: cubicBezier(0, -0.5, 1, -0.5)
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
gEffectEasingTests.forEach(function(options) {
|
gEffectEasingTests.forEach(function(options) {
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
var target = createDiv(t);
|
var target = createDiv(t);
|
||||||
|
@ -694,7 +647,7 @@ var gStepTimingFunctionTests = [
|
||||||
{ currentTime: 2500, progress: 0.5 },
|
{ currentTime: 2500, progress: 0.5 },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
||||||
gStepTimingFunctionTests.forEach(function(options) {
|
gStepTimingFunctionTests.forEach(function(options) {
|
||||||
test(function(t) {
|
test(function(t) {
|
||||||
|
|
|
@ -70,6 +70,46 @@ test(function(t) {
|
||||||
}, 'Overlapping keyframes between 0 and 1 use the appropriate value on each'
|
}, 'Overlapping keyframes between 0 and 1 use the appropriate value on each'
|
||||||
+ ' side of the overlap point');
|
+ ' side of the overlap point');
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate({ visibility: ['hidden','visible'] },
|
||||||
|
{ duration: 100 * MS_PER_SEC, fill: 'both' });
|
||||||
|
|
||||||
|
anim.currentTime = 0;
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||||
|
'Visibility when progress = 0.');
|
||||||
|
|
||||||
|
anim.currentTime = 10 * MS_PER_SEC + 1;
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||||
|
'Visibility when progress > 0 due to linear easing.');
|
||||||
|
|
||||||
|
anim.finish();
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||||
|
'Visibility when progress = 1.');
|
||||||
|
|
||||||
|
}, "Test visibility clamping behavior.");
|
||||||
|
|
||||||
|
test(function(t) {
|
||||||
|
var div = createDiv(t);
|
||||||
|
var anim = div.animate({ visibility: ['hidden', 'visible'] },
|
||||||
|
{ duration: 100 * MS_PER_SEC, fill: 'both',
|
||||||
|
easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' });
|
||||||
|
|
||||||
|
anim.currentTime = 0;
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||||
|
'Visibility when progress = 0.');
|
||||||
|
|
||||||
|
// Timing function is below zero. So we expected visibility is hidden.
|
||||||
|
anim.currentTime = 10 * MS_PER_SEC + 1;
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'hidden',
|
||||||
|
'Visibility when progress < 0 due to cubic-bezier easing.');
|
||||||
|
|
||||||
|
anim.currentTime = 60 * MS_PER_SEC;
|
||||||
|
assert_equals(getComputedStyle(div).visibility, 'visible',
|
||||||
|
'Visibility when progress > 0 due to cubic-bezier easing.');
|
||||||
|
|
||||||
|
}, "Test visibility clamping behavior with an easing that has a negative component");
|
||||||
|
|
||||||
done();
|
done();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
var gEffectEasingTests = [
|
||||||
|
{
|
||||||
|
desc: 'steps(start) function',
|
||||||
|
easing: 'steps(2, start)',
|
||||||
|
easingFunction: stepStart(2)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'steps(end) function',
|
||||||
|
easing: 'steps(2, end)',
|
||||||
|
easingFunction: stepEnd(2)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'linear function',
|
||||||
|
easing: 'linear', // cubic-bezier(0, 0, 1.0, 1.0)
|
||||||
|
easingFunction: cubicBezier(0, 0, 1.0, 1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'ease function',
|
||||||
|
easing: 'ease', // cubic-bezier(0.25, 0.1, 0.25, 1.0)
|
||||||
|
easingFunction: cubicBezier(0.25, 0.1, 0.25, 1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'ease-in function',
|
||||||
|
easing: 'ease-in', // cubic-bezier(0.42, 0, 1.0, 1.0)
|
||||||
|
easingFunction: cubicBezier(0.42, 0, 1.0, 1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'ease-in-out function',
|
||||||
|
easing: 'ease-in-out', // cubic-bezier(0.42, 0, 0.58, 1.0)
|
||||||
|
easingFunction: cubicBezier(0.42, 0, 0.58, 1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'ease-out function',
|
||||||
|
easing: 'ease-out', // cubic-bezier(0, 0, 0.58, 1.0)
|
||||||
|
easingFunction: cubicBezier(0, 0, 0.58, 1.0)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: 'easing function which produces values greater than 1',
|
||||||
|
easing: 'cubic-bezier(0, 1.5, 1, 1.5)',
|
||||||
|
easingFunction: cubicBezier(0, 1.5, 1, 1.5)
|
||||||
|
}
|
||||||
|
];
|
|
@ -6,9 +6,9 @@
|
||||||
<div id=log></div>
|
<div id=log></div>
|
||||||
<script>
|
<script>
|
||||||
async_test(function(t) {
|
async_test(function(t) {
|
||||||
var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-query?x\u0000');
|
var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-query?x\u0000y\u0000');
|
||||||
ws.onmessage = t.step_func(function(e) {
|
ws.onmessage = t.step_func(function(e) {
|
||||||
assert_equals(e.data, 'x%00');
|
assert_equals(e.data, 'x%00y');
|
||||||
ws.close();
|
ws.close();
|
||||||
t.done();
|
t.done();
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue