mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-06 17:48:37 +00:00
Tests: Import a bunch of WPT tests from /dom/events
This commit is contained in:
parent
0339ece565
commit
aa9ed71ff3
Notes:
github-actions[bot]
2024-11-17 13:57:32 +00:00
Author: https://github.com/awesomekling
Commit: aa9ed71ff3
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2394
125 changed files with 6002 additions and 0 deletions
|
@ -0,0 +1,58 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 48 tests
|
||||||
|
|
||||||
|
48 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Set HTMLBodyElement.onblur
|
||||||
|
Pass Enumerate HTMLBodyElement.onblur
|
||||||
|
Pass Reflect HTMLBodyElement.onblur
|
||||||
|
Pass Forward HTMLBodyElement.onblur to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onblur
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onblur
|
||||||
|
Pass Reflect HTMLFrameSetElement.onblur
|
||||||
|
Pass Forward HTMLFrameSetElement.onblur to Window
|
||||||
|
Pass Set HTMLBodyElement.onerror
|
||||||
|
Pass Enumerate HTMLBodyElement.onerror
|
||||||
|
Pass Reflect HTMLBodyElement.onerror
|
||||||
|
Pass Forward HTMLBodyElement.onerror to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onerror
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onerror
|
||||||
|
Pass Reflect HTMLFrameSetElement.onerror
|
||||||
|
Pass Forward HTMLFrameSetElement.onerror to Window
|
||||||
|
Pass Set HTMLBodyElement.onfocus
|
||||||
|
Pass Enumerate HTMLBodyElement.onfocus
|
||||||
|
Pass Reflect HTMLBodyElement.onfocus
|
||||||
|
Pass Forward HTMLBodyElement.onfocus to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onfocus
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onfocus
|
||||||
|
Pass Reflect HTMLFrameSetElement.onfocus
|
||||||
|
Pass Forward HTMLFrameSetElement.onfocus to Window
|
||||||
|
Pass Set HTMLBodyElement.onload
|
||||||
|
Pass Enumerate HTMLBodyElement.onload
|
||||||
|
Pass Reflect HTMLBodyElement.onload
|
||||||
|
Pass Forward HTMLBodyElement.onload to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onload
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onload
|
||||||
|
Pass Reflect HTMLFrameSetElement.onload
|
||||||
|
Pass Forward HTMLFrameSetElement.onload to Window
|
||||||
|
Pass Set HTMLBodyElement.onscroll
|
||||||
|
Pass Enumerate HTMLBodyElement.onscroll
|
||||||
|
Pass Reflect HTMLBodyElement.onscroll
|
||||||
|
Pass Forward HTMLBodyElement.onscroll to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onscroll
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onscroll
|
||||||
|
Pass Reflect HTMLFrameSetElement.onscroll
|
||||||
|
Pass Forward HTMLFrameSetElement.onscroll to Window
|
||||||
|
Pass Set HTMLBodyElement.onresize
|
||||||
|
Pass Enumerate HTMLBodyElement.onresize
|
||||||
|
Pass Reflect HTMLBodyElement.onresize
|
||||||
|
Pass Forward HTMLBodyElement.onresize to Window
|
||||||
|
Pass Set HTMLFrameSetElement.onresize
|
||||||
|
Pass Enumerate HTMLFrameSetElement.onresize
|
||||||
|
Pass Reflect HTMLFrameSetElement.onresize
|
||||||
|
Pass Forward HTMLFrameSetElement.onresize to Window
|
|
@ -0,0 +1,13 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 3 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass CustomEvent dispatching.
|
||||||
|
Pass First parameter to initCustomEvent should be mandatory.
|
||||||
|
Pass initCustomEvent's default parameter values.
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
8 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass cancelBubble must be false when an event is initially created.
|
||||||
|
Pass Initializing an event must set cancelBubble to false.
|
||||||
|
Pass stopPropagation() must set cancelBubble to true.
|
||||||
|
Pass stopImmediatePropagation() must set cancelBubble to true.
|
||||||
|
Pass Event.cancelBubble=false must have no effect.
|
||||||
|
Pass Event.cancelBubble=false must have no effect during event propagation.
|
||||||
|
Pass cancelBubble must be false after an event has been dispatched.
|
||||||
|
Pass Event.cancelBubble=true must set the stop propagation flag.
|
|
@ -0,0 +1,10 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: Error
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found tests
|
||||||
|
|
||||||
|
Details
|
||||||
|
Result Test Name Message
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Default prevention via preventDefault
|
||||||
|
Pass Default prevention via returnValue
|
|
@ -0,0 +1,18 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
8 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass When an event is created, defaultPrevented should be initialized to false.
|
||||||
|
Pass initEvent should work correctly (not cancelable).
|
||||||
|
Pass preventDefault() should not change defaultPrevented if cancelable is false.
|
||||||
|
Pass returnValue should not change defaultPrevented if cancelable is false.
|
||||||
|
Pass initEvent should work correctly (cancelable).
|
||||||
|
Pass preventDefault() should change defaultPrevented if cancelable is true.
|
||||||
|
Pass returnValue should change defaultPrevented if cancelable is true.
|
||||||
|
Pass initEvent should unset defaultPrevented.
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Setting cancelBubble=true prior to dispatchEvent()
|
|
@ -0,0 +1,16 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 5 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail In window.document with click event
|
||||||
|
Pass In window.document with load event
|
||||||
|
Pass In window.document.cloneNode(true)
|
||||||
|
Pass In new Document()
|
||||||
|
Pass In DOMImplementation.createHTMLDocument()
|
|
@ -0,0 +1,16 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 5 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail In window.document with click event
|
||||||
|
Pass In window.document with load event
|
||||||
|
Pass In window.document.cloneNode(true)
|
||||||
|
Pass In new Document()
|
||||||
|
Pass In DOMImplementation.createHTMLDocument()
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
2 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass disabled checkbox should not be checked from label click
|
||||||
|
Pass disabled radio should not be checked from label click
|
||||||
|
Pass disabled checkbox should not be checked from label click by dispatchEvent
|
||||||
|
Pass disabled radio should not be checked from label click by dispatchEvent
|
||||||
|
Fail checkbox morphed into another type should not mutate checked state
|
||||||
|
Fail radio morphed into another type should not steal the existing checked state
|
|
@ -0,0 +1,44 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 33 tests
|
||||||
|
|
||||||
|
30 Pass
|
||||||
|
3 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass basic with click()
|
||||||
|
Pass basic with dispatchEvent()
|
||||||
|
Pass basic with wrong event class
|
||||||
|
Pass look at parents only when event bubbles
|
||||||
|
Pass look at parents when event bubbles
|
||||||
|
Pass pick the first with activation behavior <input type=checkbox>
|
||||||
|
Pass pick the first with activation behavior <a href>
|
||||||
|
Pass pick the first with activation behavior <input type=radio>
|
||||||
|
Pass event state during post-click handling
|
||||||
|
Pass redispatch during post-click handling
|
||||||
|
Pass disabled checkbox still has activation behavior
|
||||||
|
Pass disabled checkbox still has activation behavior, part 2
|
||||||
|
Pass disabled radio still has activation behavior
|
||||||
|
Pass disconnected checkbox should be checked
|
||||||
|
Pass disconnected radio should be checked
|
||||||
|
Pass disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))
|
||||||
|
Pass disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))
|
||||||
|
Pass disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))
|
||||||
|
Pass disabled radio should be checked from dispatchEvent(new MouseEvent("click"))
|
||||||
|
Pass disabled checkbox should fire onclick
|
||||||
|
Pass disabled radio should fire onclick
|
||||||
|
Pass disabled checkbox should get legacy-canceled-activation behavior
|
||||||
|
Pass disabled radio should get legacy-canceled-activation behavior
|
||||||
|
Pass disabled checkbox should get legacy-canceled-activation behavior 2
|
||||||
|
Pass disabled radio should get legacy-canceled-activation behavior 2
|
||||||
|
Pass disabling checkbox in onclick listener shouldn't suppress oninput
|
||||||
|
Pass disabling checkbox in onclick listener shouldn't suppress onchange
|
||||||
|
Pass disabling radio in onclick listener shouldn't suppress oninput
|
||||||
|
Pass disabling radio in onclick listener shouldn't suppress onchange
|
||||||
|
Pass disconnected form should not submit
|
||||||
|
Fail disabled submit button should not activate
|
||||||
|
Fail submit button should not activate if the event listener disables it
|
||||||
|
Fail submit button that morphed from checkbox should not activate
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Click event on an element not in the document
|
||||||
|
Pass Click event can be dispatched to an element that is not in the document.
|
|
@ -0,0 +1,22 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 12 tests
|
||||||
|
|
||||||
|
12 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass detached checkbox should not emit input or change events on click().
|
||||||
|
Pass detached radio should not emit input or change events on click().
|
||||||
|
Pass detached checkbox should not emit input or change events on dispatchEvent(new MouseEvent('click')).
|
||||||
|
Pass detached radio should not emit input or change events on dispatchEvent(new MouseEvent('click')).
|
||||||
|
Pass attached checkbox should emit input and change events on click().
|
||||||
|
Pass attached radio should emit input and change events on click().
|
||||||
|
Pass attached checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).
|
||||||
|
Pass attached radio should emit input and change events on dispatchEvent(new MouseEvent('click')).
|
||||||
|
Pass attached to shadow dom checkbox should emit input and change events on click().
|
||||||
|
Pass attached to shadow dom radio should emit input and change events on click().
|
||||||
|
Pass attached to shadow dom checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).
|
||||||
|
Pass attached to shadow dom radio should emit input and change events on dispatchEvent(new MouseEvent('click')).
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Dispatch additional events inside an event listener
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Multiple dispatchEvent() and cancelBubble
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Multiple dispatchEvent() and stopPropagation()
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail EventTarget.addEventListener with the capture argument omitted
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Listeners are invoked in correct order (AT_TARGET phase)
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Event phases order
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Custom event on an element in another document
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Calling stopPropagation() prior to dispatchEvent()
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Dispatch additional events inside an event listener
|
|
@ -0,0 +1,143 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 132 tests
|
||||||
|
|
||||||
|
103 Pass
|
||||||
|
29 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass When clicking child <INPUT type=checkbox></INPUT> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=checkbox></INPUT> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <INPUT type=radio></INPUT> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=submit></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=image></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><INPUT type=reset></INPUT></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=submit></BUTTON></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <FORM><BUTTON type=reset></BUTTON></FORM> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <A></A> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <AREA></AREA> of parent <A></A>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Fail When clicking child <AREA></AREA> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <DETAILS><SUMMARY></SUMMARY></DETAILS> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <A></A>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Fail When clicking child <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL> of parent <LABEL><BUTTON type=button></BUTTON></LABEL>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <INPUT type=checkbox></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <INPUT type=radio></INPUT>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=submit></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=image></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><INPUT type=reset></INPUT></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><BUTTON type=submit></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <FORM><BUTTON type=reset></BUTTON></FORM>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <A></A>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <AREA></AREA>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <DETAILS><SUMMARY></SUMMARY></DETAILS>, only child should be activated.
|
||||||
|
Pass When clicking child <LABEL><BUTTON type=button></BUTTON></LABEL> of parent <LABEL><INPUT type=checkbox></INPUT><SPAN></SPAN></LABEL>, only child should be activated.
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Event propagation path when an element in it is moved within the DOM
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Event propagation path when an element in it is removed from the DOM
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail exception thrown in event listener function should result in error event on listener's global
|
||||||
|
Fail exception thrown in event listener interface object should result in error event on listener's global
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Throwing in event listener with a single listeners
|
||||||
|
Pass Throwing in event listener with multiple listeners
|
|
@ -0,0 +1,16 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 5 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Calling initKeyboardEvent while dispatching.
|
||||||
|
Pass Calling initMouseEvent while dispatching.
|
||||||
|
Pass Calling initCustomEvent while dispatching.
|
||||||
|
Fail Calling initUIEvent while dispatching. Not an object of type Window
|
||||||
|
Pass Calling initEvent while dispatching.
|
|
@ -0,0 +1,22 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 12 tests
|
||||||
|
|
||||||
|
12 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Properties of initEvent(type, true, true)
|
||||||
|
Pass Properties of initEvent(type, true, false)
|
||||||
|
Pass Properties of initEvent(type, false, true)
|
||||||
|
Pass Properties of initEvent(type, false, false)
|
||||||
|
Pass Calling initEvent multiple times (getting type).
|
||||||
|
Pass Calling initEvent multiple times (not getting type).
|
||||||
|
Pass Calling initEvent must not have an effect during dispatching.
|
||||||
|
Pass Calling initEvent must unset the stop propagation flag.
|
||||||
|
Pass Calling initEvent must unset the stop immediate propagation flag.
|
||||||
|
Pass Calling initEvent during propagation.
|
||||||
|
Pass First parameter to initEvent should be mandatory.
|
||||||
|
Pass Tests initEvent's default parameter values.
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 7 tests
|
||||||
|
|
||||||
|
7 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Newly-created Event
|
||||||
|
Pass After stopPropagation()
|
||||||
|
Pass Reinitialized after stopPropagation()
|
||||||
|
Pass After stopImmediatePropagation()
|
||||||
|
Pass Reinitialized after stopImmediatePropagation()
|
||||||
|
Pass After cancelBubble=true
|
||||||
|
Pass Reinitialized after cancelBubble=true
|
|
@ -0,0 +1,17 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 7 tests
|
||||||
|
|
||||||
|
7 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass When an event is created, returnValue should be initialized to true.
|
||||||
|
Pass preventDefault() should not change returnValue if cancelable is false.
|
||||||
|
Pass returnValue=false should have no effect if cancelable is false.
|
||||||
|
Pass preventDefault() should change returnValue if cancelable is true.
|
||||||
|
Pass returnValue should change returnValue if cancelable is true.
|
||||||
|
Pass initEvent should unset returnValue.
|
||||||
|
Pass returnValue=true should have no effect once the canceled flag was set.
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Event's stopImmediatePropagation
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Event-stopPropagation-cancel-bubbling
|
|
@ -0,0 +1,60 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 49 tests
|
||||||
|
|
||||||
|
43 Pass
|
||||||
|
6 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Event constructor (no argument)
|
||||||
|
Pass Event constructor (undefined argument)
|
||||||
|
Pass Event constructor (null argument)
|
||||||
|
Pass Event constructor (empty argument)
|
||||||
|
Pass Event constructor (argument with default values)
|
||||||
|
Pass Event constructor (argument with non-default values)
|
||||||
|
Pass UIEvent constructor (no argument)
|
||||||
|
Pass UIEvent constructor (undefined argument)
|
||||||
|
Pass UIEvent constructor (null argument)
|
||||||
|
Pass UIEvent constructor (empty argument)
|
||||||
|
Pass UIEvent constructor (argument with default values)
|
||||||
|
Fail UIEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass FocusEvent constructor (no argument)
|
||||||
|
Pass FocusEvent constructor (undefined argument)
|
||||||
|
Pass FocusEvent constructor (null argument)
|
||||||
|
Pass FocusEvent constructor (empty argument)
|
||||||
|
Pass FocusEvent constructor (argument with default values)
|
||||||
|
Fail FocusEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass MouseEvent constructor (no argument)
|
||||||
|
Pass MouseEvent constructor (undefined argument)
|
||||||
|
Pass MouseEvent constructor (null argument)
|
||||||
|
Pass MouseEvent constructor (empty argument)
|
||||||
|
Pass MouseEvent constructor (argument with default values)
|
||||||
|
Fail MouseEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass WheelEvent constructor (no argument)
|
||||||
|
Pass WheelEvent constructor (undefined argument)
|
||||||
|
Pass WheelEvent constructor (null argument)
|
||||||
|
Pass WheelEvent constructor (empty argument)
|
||||||
|
Pass WheelEvent constructor (argument with default values)
|
||||||
|
Fail WheelEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass KeyboardEvent constructor (no argument)
|
||||||
|
Pass KeyboardEvent constructor (undefined argument)
|
||||||
|
Pass KeyboardEvent constructor (null argument)
|
||||||
|
Pass KeyboardEvent constructor (empty argument)
|
||||||
|
Pass KeyboardEvent constructor (argument with default values)
|
||||||
|
Fail KeyboardEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass CompositionEvent constructor (no argument)
|
||||||
|
Pass CompositionEvent constructor (undefined argument)
|
||||||
|
Pass CompositionEvent constructor (null argument)
|
||||||
|
Pass CompositionEvent constructor (empty argument)
|
||||||
|
Pass CompositionEvent constructor (argument with default values)
|
||||||
|
Fail CompositionEvent constructor (argument with non-default values) Not an object of type Window
|
||||||
|
Pass SubclassedEvent constructor (no argument)
|
||||||
|
Pass SubclassedEvent constructor (undefined argument)
|
||||||
|
Pass SubclassedEvent constructor (null argument)
|
||||||
|
Pass SubclassedEvent constructor (empty argument)
|
||||||
|
Pass SubclassedEvent constructor (argument with default values)
|
||||||
|
Pass SubclassedEvent constructor (argument with non-default values)
|
||||||
|
Pass UIEvent constructor (view argument with wrong type)
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass event.timeStamp is initialized using event's relevant global object
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Constructed GamepadEvent timestamp should be high resolution and have the same time origin as performance.now() undefined is not a constructor (evaluated from 'window[<computed>]')
|
|
@ -0,0 +1,14 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 4 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Constructed MouseEvent timestamp should be high resolution and have the same time origin as performance.now()
|
||||||
|
Pass Constructed KeyboardEvent timestamp should be high resolution and have the same time origin as performance.now()
|
||||||
|
Pass Constructed WheelEvent timestamp should be high resolution and have the same time origin as performance.now()
|
||||||
|
Pass Constructed FocusEvent timestamp should be high resolution and have the same time origin as performance.now()
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail Event timestamp should not have a resolution better than 5 microseconds
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass initEvent
|
||||||
|
Pass Constructor
|
|
@ -0,0 +1,13 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 3 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Event.type should initially be the empty string
|
||||||
|
Pass Event.type should be initialized by initEvent
|
||||||
|
Pass Event.type should be initialized by the constructor
|
|
@ -0,0 +1,16 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
6 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass calls `handleEvent` method of `EventListener`
|
||||||
|
Pass performs `Get` every time event is dispatched
|
||||||
|
Pass doesn't call `handleEvent` method on callable `EventListener`
|
||||||
|
Pass rethrows errors when getting `handleEvent`
|
||||||
|
Pass throws if `handleEvent` is falsy and not callable
|
||||||
|
Pass throws if `handleEvent` is thruthy and not callable
|
|
@ -0,0 +1,14 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 4 tests
|
||||||
|
|
||||||
|
4 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Capture boolean should be honored correctly
|
||||||
|
Pass Capture option should be honored correctly
|
||||||
|
Pass Supports capture option
|
||||||
|
Pass Equivalence of option values
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass addEventListener with a platform object
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Return value of EventTarget.dispatchEvent() affected by preventDefault().
|
||||||
|
Pass Return value of EventTarget.dispatchEvent() affected by returnValue.
|
|
@ -0,0 +1,35 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 25 tests
|
||||||
|
|
||||||
|
25 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Calling dispatchEvent(null).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (BeforeUnloadEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (CompositionEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (CustomEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceMotionEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (DeviceOrientationEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (DragEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (Event).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (Events).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (FocusEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (HashChangeEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (HTMLEvents).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (KeyboardEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (MessageEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (MouseEvents).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (StorageEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (SVGEvents).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (TextEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvent).
|
||||||
|
Pass If the event's initialized flag is not set, an InvalidStateError must be thrown (UIEvents).
|
||||||
|
Pass If the event's dispatch flag is set, an InvalidStateError must be thrown.
|
||||||
|
Pass Exceptions from event listeners must not be propagated.
|
||||||
|
Pass Event listeners added during dispatch should be called
|
||||||
|
Pass Capturing event listeners should be called before non-capturing ones
|
|
@ -0,0 +1,16 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 6 tests
|
||||||
|
|
||||||
|
6 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass the this value inside the event listener callback should be the node
|
||||||
|
Pass the this value inside the event listener object handleEvent should be the object
|
||||||
|
Pass dispatchEvent should invoke the current handleEvent method of the object
|
||||||
|
Pass addEventListener should not require handleEvent to be defined on object listeners
|
||||||
|
Pass handleEvent properties added to a function before addEventListener are not reached
|
||||||
|
Pass handleEvent properties added to a function after addEventListener are not reached
|
|
@ -0,0 +1,13 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 3 tests
|
||||||
|
|
||||||
|
3 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass KeyboardEvent.initKeyEvent shouldn't be defined (created by createEvent("KeyboardEvent")
|
||||||
|
Pass KeyboardEvent.initKeyEvent shouldn't be defined (created by constructor)
|
||||||
|
Pass KeyboardEvent.prototype.initKeyEvent shouldn't be defined
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass disabled is honored properly in presence of dynamic changes
|
|
@ -0,0 +1,19 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 8 tests
|
||||||
|
|
||||||
|
7 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass event exists on window, which is initially set to undefined
|
||||||
|
Pass window.event is only defined during dispatch
|
||||||
|
Pass window.event is undefined if the target is in a shadow tree (event dispatched outside shadow tree)
|
||||||
|
Pass window.event is undefined if the target is in a shadow tree (event dispatched inside shadow tree)
|
||||||
|
Fail window.event is undefined inside window.onerror if the target is in a shadow tree (ErrorEvent dispatched inside shadow tree)
|
||||||
|
Pass window.event is set to the current event during dispatch
|
||||||
|
Pass window.event is set to the current event, which is the event passed to dispatch
|
||||||
|
Pass window.event is set to the current event, which is the event passed to dispatch (2)
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail offsetX is correctly adjusted
|
|
@ -0,0 +1,111 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 100 tests
|
||||||
|
|
||||||
|
68 Pass
|
||||||
|
32 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail touchstart listener is passive by default for Window
|
||||||
|
Fail touchstart listener is passive with {passive:undefined} for Window
|
||||||
|
Pass touchstart listener is non-passive with {passive:false} for Window
|
||||||
|
Pass touchstart listener is passive with {passive:true} for Window
|
||||||
|
Fail touchstart listener is passive by default for HTMLDocument
|
||||||
|
Fail touchstart listener is passive with {passive:undefined} for HTMLDocument
|
||||||
|
Pass touchstart listener is non-passive with {passive:false} for HTMLDocument
|
||||||
|
Pass touchstart listener is passive with {passive:true} for HTMLDocument
|
||||||
|
Fail touchstart listener is passive by default for HTMLHtmlElement
|
||||||
|
Fail touchstart listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||||
|
Pass touchstart listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||||
|
Pass touchstart listener is passive with {passive:true} for HTMLHtmlElement
|
||||||
|
Fail touchstart listener is passive by default for HTMLBodyElement
|
||||||
|
Fail touchstart listener is passive with {passive:undefined} for HTMLBodyElement
|
||||||
|
Pass touchstart listener is non-passive with {passive:false} for HTMLBodyElement
|
||||||
|
Pass touchstart listener is passive with {passive:true} for HTMLBodyElement
|
||||||
|
Pass touchstart listener is non-passive by default for HTMLDivElement
|
||||||
|
Pass touchstart listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||||
|
Pass touchstart listener is non-passive with {passive:false} for HTMLDivElement
|
||||||
|
Pass touchstart listener is passive with {passive:true} for HTMLDivElement
|
||||||
|
Fail touchmove listener is passive by default for Window
|
||||||
|
Fail touchmove listener is passive with {passive:undefined} for Window
|
||||||
|
Pass touchmove listener is non-passive with {passive:false} for Window
|
||||||
|
Pass touchmove listener is passive with {passive:true} for Window
|
||||||
|
Fail touchmove listener is passive by default for HTMLDocument
|
||||||
|
Fail touchmove listener is passive with {passive:undefined} for HTMLDocument
|
||||||
|
Pass touchmove listener is non-passive with {passive:false} for HTMLDocument
|
||||||
|
Pass touchmove listener is passive with {passive:true} for HTMLDocument
|
||||||
|
Fail touchmove listener is passive by default for HTMLHtmlElement
|
||||||
|
Fail touchmove listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||||
|
Pass touchmove listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||||
|
Pass touchmove listener is passive with {passive:true} for HTMLHtmlElement
|
||||||
|
Fail touchmove listener is passive by default for HTMLBodyElement
|
||||||
|
Fail touchmove listener is passive with {passive:undefined} for HTMLBodyElement
|
||||||
|
Pass touchmove listener is non-passive with {passive:false} for HTMLBodyElement
|
||||||
|
Pass touchmove listener is passive with {passive:true} for HTMLBodyElement
|
||||||
|
Pass touchmove listener is non-passive by default for HTMLDivElement
|
||||||
|
Pass touchmove listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||||
|
Pass touchmove listener is non-passive with {passive:false} for HTMLDivElement
|
||||||
|
Pass touchmove listener is passive with {passive:true} for HTMLDivElement
|
||||||
|
Fail wheel listener is passive by default for Window
|
||||||
|
Fail wheel listener is passive with {passive:undefined} for Window
|
||||||
|
Pass wheel listener is non-passive with {passive:false} for Window
|
||||||
|
Pass wheel listener is passive with {passive:true} for Window
|
||||||
|
Fail wheel listener is passive by default for HTMLDocument
|
||||||
|
Fail wheel listener is passive with {passive:undefined} for HTMLDocument
|
||||||
|
Pass wheel listener is non-passive with {passive:false} for HTMLDocument
|
||||||
|
Pass wheel listener is passive with {passive:true} for HTMLDocument
|
||||||
|
Fail wheel listener is passive by default for HTMLHtmlElement
|
||||||
|
Fail wheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||||
|
Pass wheel listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||||
|
Pass wheel listener is passive with {passive:true} for HTMLHtmlElement
|
||||||
|
Fail wheel listener is passive by default for HTMLBodyElement
|
||||||
|
Fail wheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||||
|
Pass wheel listener is non-passive with {passive:false} for HTMLBodyElement
|
||||||
|
Pass wheel listener is passive with {passive:true} for HTMLBodyElement
|
||||||
|
Pass wheel listener is non-passive by default for HTMLDivElement
|
||||||
|
Pass wheel listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||||
|
Pass wheel listener is non-passive with {passive:false} for HTMLDivElement
|
||||||
|
Pass wheel listener is passive with {passive:true} for HTMLDivElement
|
||||||
|
Fail mousewheel listener is passive by default for Window
|
||||||
|
Fail mousewheel listener is passive with {passive:undefined} for Window
|
||||||
|
Pass mousewheel listener is non-passive with {passive:false} for Window
|
||||||
|
Pass mousewheel listener is passive with {passive:true} for Window
|
||||||
|
Fail mousewheel listener is passive by default for HTMLDocument
|
||||||
|
Fail mousewheel listener is passive with {passive:undefined} for HTMLDocument
|
||||||
|
Pass mousewheel listener is non-passive with {passive:false} for HTMLDocument
|
||||||
|
Pass mousewheel listener is passive with {passive:true} for HTMLDocument
|
||||||
|
Fail mousewheel listener is passive by default for HTMLHtmlElement
|
||||||
|
Fail mousewheel listener is passive with {passive:undefined} for HTMLHtmlElement
|
||||||
|
Pass mousewheel listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||||
|
Pass mousewheel listener is passive with {passive:true} for HTMLHtmlElement
|
||||||
|
Fail mousewheel listener is passive by default for HTMLBodyElement
|
||||||
|
Fail mousewheel listener is passive with {passive:undefined} for HTMLBodyElement
|
||||||
|
Pass mousewheel listener is non-passive with {passive:false} for HTMLBodyElement
|
||||||
|
Pass mousewheel listener is passive with {passive:true} for HTMLBodyElement
|
||||||
|
Pass mousewheel listener is non-passive by default for HTMLDivElement
|
||||||
|
Pass mousewheel listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||||
|
Pass mousewheel listener is non-passive with {passive:false} for HTMLDivElement
|
||||||
|
Pass mousewheel listener is passive with {passive:true} for HTMLDivElement
|
||||||
|
Pass touchend listener is non-passive by default for Window
|
||||||
|
Pass touchend listener is non-passive with {passive:undefined} for Window
|
||||||
|
Pass touchend listener is non-passive with {passive:false} for Window
|
||||||
|
Pass touchend listener is passive with {passive:true} for Window
|
||||||
|
Pass touchend listener is non-passive by default for HTMLDocument
|
||||||
|
Pass touchend listener is non-passive with {passive:undefined} for HTMLDocument
|
||||||
|
Pass touchend listener is non-passive with {passive:false} for HTMLDocument
|
||||||
|
Pass touchend listener is passive with {passive:true} for HTMLDocument
|
||||||
|
Pass touchend listener is non-passive by default for HTMLHtmlElement
|
||||||
|
Pass touchend listener is non-passive with {passive:undefined} for HTMLHtmlElement
|
||||||
|
Pass touchend listener is non-passive with {passive:false} for HTMLHtmlElement
|
||||||
|
Pass touchend listener is passive with {passive:true} for HTMLHtmlElement
|
||||||
|
Pass touchend listener is non-passive by default for HTMLBodyElement
|
||||||
|
Pass touchend listener is non-passive with {passive:undefined} for HTMLBodyElement
|
||||||
|
Pass touchend listener is non-passive with {passive:false} for HTMLBodyElement
|
||||||
|
Pass touchend listener is passive with {passive:true} for HTMLBodyElement
|
||||||
|
Pass touchend listener is non-passive by default for HTMLDivElement
|
||||||
|
Pass touchend listener is non-passive with {passive:undefined} for HTMLDivElement
|
||||||
|
Pass touchend listener is non-passive with {passive:false} for HTMLDivElement
|
||||||
|
Pass touchend listener is passive with {passive:true} for HTMLDivElement
|
|
@ -0,0 +1,11 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 1 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass behavior of preventDefault during activation behavior
|
|
@ -0,0 +1,13 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
1 Pass
|
||||||
|
1 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessagePass Removing all listeners and then adding a new one should work.
|
||||||
|
Fail Nested usage of once listeners should work.
|
|
@ -0,0 +1,12 @@
|
||||||
|
Summary
|
||||||
|
|
||||||
|
Harness status: OK
|
||||||
|
|
||||||
|
Rerun
|
||||||
|
|
||||||
|
Found 2 tests
|
||||||
|
|
||||||
|
2 Fail
|
||||||
|
Details
|
||||||
|
Result Test Name MessageFail relatedTarget should not leak at capturing phase, at window object.
|
||||||
|
Fail relatedTarget should not leak at target.
|
|
@ -0,0 +1,96 @@
|
||||||
|
// META: title=AddEventListenerOptions.once
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var invoked_once = false;
|
||||||
|
var invoked_normal = false;
|
||||||
|
function handler_once() {
|
||||||
|
invoked_once = true;
|
||||||
|
}
|
||||||
|
function handler_normal() {
|
||||||
|
invoked_normal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const et = new EventTarget();
|
||||||
|
et.addEventListener('test', handler_once, {once: true});
|
||||||
|
et.addEventListener('test', handler_normal);
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_once, true, "Once handler should be invoked");
|
||||||
|
assert_equals(invoked_normal, true, "Normal handler should be invoked");
|
||||||
|
|
||||||
|
invoked_once = false;
|
||||||
|
invoked_normal = false;
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_once, false, "Once handler shouldn't be invoked again");
|
||||||
|
assert_equals(invoked_normal, true, "Normal handler should be invoked again");
|
||||||
|
et.removeEventListener('test', handler_normal);
|
||||||
|
}, "Once listener should be invoked only once");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const et = new EventTarget();
|
||||||
|
var invoked_count = 0;
|
||||||
|
function handler() {
|
||||||
|
invoked_count++;
|
||||||
|
if (invoked_count == 1)
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
}
|
||||||
|
et.addEventListener('test', handler, {once: true});
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_count, 1, "Once handler should only be invoked once");
|
||||||
|
|
||||||
|
invoked_count = 0;
|
||||||
|
function handler2() {
|
||||||
|
invoked_count++;
|
||||||
|
if (invoked_count == 1)
|
||||||
|
et.addEventListener('test', handler2, {once: true});
|
||||||
|
if (invoked_count <= 2)
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
}
|
||||||
|
et.addEventListener('test', handler2, {once: true});
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_count, 2, "Once handler should only be invoked once after each adding");
|
||||||
|
}, "Once listener should be invoked only once even if the event is nested");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var invoked_count = 0;
|
||||||
|
function handler() {
|
||||||
|
invoked_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const et = new EventTarget();
|
||||||
|
|
||||||
|
et.addEventListener('test', handler, {once: true});
|
||||||
|
et.addEventListener('test', handler);
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_count, 1, "The handler should only be added once");
|
||||||
|
|
||||||
|
invoked_count = 0;
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_count, 0, "The handler was added as a once listener");
|
||||||
|
|
||||||
|
invoked_count = 0;
|
||||||
|
et.addEventListener('test', handler, {once: true});
|
||||||
|
et.removeEventListener('test', handler);
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(invoked_count, 0, "The handler should have been removed");
|
||||||
|
}, "Once listener should be added / removed like normal listeners");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const et = new EventTarget();
|
||||||
|
|
||||||
|
var invoked_count = 0;
|
||||||
|
|
||||||
|
for (let n = 4; n > 0; n--) {
|
||||||
|
et.addEventListener('test', (e) => {
|
||||||
|
invoked_count++;
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
}, {once: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let n = 4; n > 0; n--) {
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equals(invoked_count, 4, "The listeners should be invoked");
|
||||||
|
}, "Multiple once listeners should be invoked even if the stopImmediatePropagation is set");
|
|
@ -0,0 +1,134 @@
|
||||||
|
// META: title=AddEventListenerOptions.passive
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var supportsPassive = false;
|
||||||
|
var query_options = {
|
||||||
|
get passive() {
|
||||||
|
supportsPassive = true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
get dummy() {
|
||||||
|
assert_unreached("dummy value getter invoked");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const et = new EventTarget();
|
||||||
|
et.addEventListener('test_event', null, query_options);
|
||||||
|
assert_true(supportsPassive, "addEventListener doesn't support the passive option");
|
||||||
|
|
||||||
|
supportsPassive = false;
|
||||||
|
et.removeEventListener('test_event', null, query_options);
|
||||||
|
assert_false(supportsPassive, "removeEventListener supports the passive option when it should not");
|
||||||
|
}, "Supports passive option on addEventListener only");
|
||||||
|
|
||||||
|
function testPassiveValue(optionsValue, expectedDefaultPrevented, existingEventTarget) {
|
||||||
|
var defaultPrevented = undefined;
|
||||||
|
var handler = function handler(e) {
|
||||||
|
assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
|
||||||
|
e.preventDefault();
|
||||||
|
defaultPrevented = e.defaultPrevented;
|
||||||
|
}
|
||||||
|
const et = existingEventTarget || new EventTarget();
|
||||||
|
et.addEventListener('test', handler, optionsValue);
|
||||||
|
var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
|
||||||
|
|
||||||
|
assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
|
||||||
|
assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
|
||||||
|
|
||||||
|
et.removeEventListener('test', handler, optionsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
testPassiveValue(undefined, true);
|
||||||
|
testPassiveValue({}, true);
|
||||||
|
testPassiveValue({passive: false}, true);
|
||||||
|
testPassiveValue({passive: true}, false);
|
||||||
|
testPassiveValue({passive: 0}, true);
|
||||||
|
testPassiveValue({passive: 1}, false);
|
||||||
|
}, "preventDefault should be ignored if-and-only-if the passive option is true");
|
||||||
|
|
||||||
|
function testPassiveValueOnReturnValue(test, optionsValue, expectedDefaultPrevented) {
|
||||||
|
var defaultPrevented = undefined;
|
||||||
|
var handler = test.step_func(e => {
|
||||||
|
assert_false(e.defaultPrevented, "Event prematurely marked defaultPrevented");
|
||||||
|
e.returnValue = false;
|
||||||
|
defaultPrevented = e.defaultPrevented;
|
||||||
|
});
|
||||||
|
const et = new EventTarget();
|
||||||
|
et.addEventListener('test', handler, optionsValue);
|
||||||
|
var uncanceled = et.dispatchEvent(new Event('test', {bubbles: true, cancelable: true}));
|
||||||
|
|
||||||
|
assert_equals(defaultPrevented, expectedDefaultPrevented, "Incorrect defaultPrevented for options: " + JSON.stringify(optionsValue));
|
||||||
|
assert_equals(uncanceled, !expectedDefaultPrevented, "Incorrect return value from dispatchEvent");
|
||||||
|
|
||||||
|
et.removeEventListener('test', handler, optionsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
testPassiveValueOnReturnValue(t, undefined, true);
|
||||||
|
testPassiveValueOnReturnValue(t, {}, true);
|
||||||
|
testPassiveValueOnReturnValue(t, {passive: false}, true);
|
||||||
|
testPassiveValueOnReturnValue(t, {passive: true}, false);
|
||||||
|
testPassiveValueOnReturnValue(t, {passive: 0}, true);
|
||||||
|
testPassiveValueOnReturnValue(t, {passive: 1}, false);
|
||||||
|
t.done();
|
||||||
|
}, "returnValue should be ignored if-and-only-if the passive option is true");
|
||||||
|
|
||||||
|
function testPassiveWithOtherHandlers(optionsValue, expectedDefaultPrevented) {
|
||||||
|
var handlerInvoked1 = false;
|
||||||
|
var dummyHandler1 = function() {
|
||||||
|
handlerInvoked1 = true;
|
||||||
|
};
|
||||||
|
var handlerInvoked2 = false;
|
||||||
|
var dummyHandler2 = function() {
|
||||||
|
handlerInvoked2 = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const et = new EventTarget();
|
||||||
|
et.addEventListener('test', dummyHandler1, {passive:true});
|
||||||
|
et.addEventListener('test', dummyHandler2);
|
||||||
|
|
||||||
|
testPassiveValue(optionsValue, expectedDefaultPrevented, et);
|
||||||
|
|
||||||
|
assert_true(handlerInvoked1, "Extra passive handler not invoked");
|
||||||
|
assert_true(handlerInvoked2, "Extra non-passive handler not invoked");
|
||||||
|
|
||||||
|
et.removeEventListener('test', dummyHandler1);
|
||||||
|
et.removeEventListener('test', dummyHandler2);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
testPassiveWithOtherHandlers({}, true);
|
||||||
|
testPassiveWithOtherHandlers({passive: false}, true);
|
||||||
|
testPassiveWithOtherHandlers({passive: true}, false);
|
||||||
|
}, "passive behavior of one listener should be unaffected by the presence of other listeners");
|
||||||
|
|
||||||
|
function testOptionEquivalence(optionValue1, optionValue2, expectedEquality) {
|
||||||
|
var invocationCount = 0;
|
||||||
|
var handler = function handler(e) {
|
||||||
|
invocationCount++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
et.addEventListener('test', handler, optionValue1);
|
||||||
|
et.addEventListener('test', handler, optionValue2);
|
||||||
|
et.dispatchEvent(new Event('test', {bubbles: true}));
|
||||||
|
assert_equals(invocationCount, expectedEquality ? 1 : 2, "equivalence of options " +
|
||||||
|
JSON.stringify(optionValue1) + " and " + JSON.stringify(optionValue2));
|
||||||
|
et.removeEventListener('test', handler, optionValue1);
|
||||||
|
et.removeEventListener('test', handler, optionValue2);
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
// Sanity check options that should be treated as distinct handlers
|
||||||
|
testOptionEquivalence({capture:true}, {capture:false, passive:false}, false);
|
||||||
|
testOptionEquivalence({capture:true}, {passive:true}, false);
|
||||||
|
|
||||||
|
// Option values that should be treated as equivalent
|
||||||
|
testOptionEquivalence({}, {passive:false}, true);
|
||||||
|
testOptionEquivalence({passive:true}, {passive:false}, true);
|
||||||
|
testOptionEquivalence(undefined, {passive:true}, true);
|
||||||
|
testOptionEquivalence({capture: true, passive: false}, {capture: true, passive: true}, true);
|
||||||
|
|
||||||
|
}, "Equivalence of option values");
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal });
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 1, "Adding a signal still adds a listener");
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 2, "The listener was not added with the once flag");
|
||||||
|
controller.abort();
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 2, "Aborting on the controller removes the listener");
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal });
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 2, "Passing an aborted signal never adds the handler");
|
||||||
|
}, "Passing an AbortSignal to addEventListener options should allow removing a listener");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal });
|
||||||
|
et.removeEventListener('test', handler);
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Passing an AbortSignal to addEventListener does not prevent removeEventListener");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal, once: true });
|
||||||
|
controller.abort();
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Passing an AbortSignal to addEventListener works with the once flag");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal, once: true });
|
||||||
|
et.removeEventListener('test', handler);
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Removing a once listener works with a passed signal");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('first', handler, { signal: controller.signal, once: true });
|
||||||
|
et.addEventListener('second', handler, { signal: controller.signal, once: true });
|
||||||
|
controller.abort();
|
||||||
|
et.dispatchEvent(new Event('first'));
|
||||||
|
et.dispatchEvent(new Event('second'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Passing an AbortSignal to multiple listeners");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal, capture: true });
|
||||||
|
controller.abort();
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Passing an AbortSignal to addEventListener works with the capture flag");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', () => {
|
||||||
|
controller.abort();
|
||||||
|
}, { signal: controller.signal });
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal });
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Aborting from a listener does not call future listeners");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
let count = 0;
|
||||||
|
function handler() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
const et = new EventTarget();
|
||||||
|
const controller = new AbortController();
|
||||||
|
et.addEventListener('test', () => {
|
||||||
|
et.addEventListener('test', handler, { signal: controller.signal });
|
||||||
|
controller.abort();
|
||||||
|
}, { signal: controller.signal });
|
||||||
|
et.dispatchEvent(new Event('test'));
|
||||||
|
assert_equals(count, 0, "The listener was still removed");
|
||||||
|
}, "Adding then aborting a listener in another listener does not call it");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const et = new EventTarget();
|
||||||
|
const ac = new AbortController();
|
||||||
|
let count = 0;
|
||||||
|
et.addEventListener('foo', () => {
|
||||||
|
et.addEventListener('foo', () => {
|
||||||
|
count++;
|
||||||
|
if (count > 5) ac.abort();
|
||||||
|
et.dispatchEvent(new Event('foo'));
|
||||||
|
}, { signal: ac.signal });
|
||||||
|
et.dispatchEvent(new Event('foo'));
|
||||||
|
}, { once: true });
|
||||||
|
et.dispatchEvent(new Event('foo'));
|
||||||
|
}, "Aborting from a nested listener should remove it");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const et = new EventTarget();
|
||||||
|
assert_throws_js(TypeError, () => { et.addEventListener("foo", () => {}, { signal: null }); });
|
||||||
|
}, "Passing null as the signal should throw");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const et = new EventTarget();
|
||||||
|
assert_throws_js(TypeError, () => { et.addEventListener("foo", null, { signal: null }); });
|
||||||
|
}, "Passing null as the signal should throw (listener is also null)");
|
|
@ -0,0 +1,123 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<title>HTMLBodyElement and HTMLFrameSetElement Event Handler Tests</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function getObject(interface) {
|
||||||
|
switch(interface) {
|
||||||
|
case "Element":
|
||||||
|
var e = document.createElementNS("http://example.com/", "example");
|
||||||
|
assert_true(e instanceof Element);
|
||||||
|
assert_false(e instanceof HTMLElement);
|
||||||
|
assert_false(e instanceof SVGElement);
|
||||||
|
return e;
|
||||||
|
case "HTMLElement":
|
||||||
|
var e = document.createElement("html");
|
||||||
|
assert_true(e instanceof HTMLElement);
|
||||||
|
return e;
|
||||||
|
case "HTMLBodyElement":
|
||||||
|
var e = document.createElement("body");
|
||||||
|
assert_true(e instanceof HTMLBodyElement);
|
||||||
|
return e;
|
||||||
|
case "HTMLFormElement":
|
||||||
|
var e = document.createElement("form");
|
||||||
|
assert_true(e instanceof HTMLFormElement);
|
||||||
|
return e;
|
||||||
|
case "HTMLFrameSetElement":
|
||||||
|
var e = document.createElement("frameset");
|
||||||
|
assert_true(e instanceof HTMLFrameSetElement);
|
||||||
|
return e;
|
||||||
|
case "SVGElement":
|
||||||
|
var e = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||||
|
assert_true(e instanceof SVGElement);
|
||||||
|
return e;
|
||||||
|
case "Document":
|
||||||
|
assert_true(document instanceof Document);
|
||||||
|
return document;
|
||||||
|
case "Window":
|
||||||
|
assert_true(window instanceof Window);
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
assert_unreached();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testSet(interface, attribute) {
|
||||||
|
test(function() {
|
||||||
|
var object = getObject(interface);
|
||||||
|
function nop() {}
|
||||||
|
assert_equals(object[attribute], null, "Initially null");
|
||||||
|
object[attribute] = nop;
|
||||||
|
assert_equals(object[attribute], nop, "Return same function");
|
||||||
|
object[attribute] = "";
|
||||||
|
assert_equals(object[attribute], null, "Return null after setting string");
|
||||||
|
object[attribute] = null;
|
||||||
|
assert_equals(object[attribute], null, "Finally null");
|
||||||
|
}, "Set " + interface + "." + attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testReflect(interface, attribute) {
|
||||||
|
test(function() {
|
||||||
|
var element = getObject(interface);
|
||||||
|
assert_false(element.hasAttribute(attribute), "Initially missing");
|
||||||
|
element.setAttribute(attribute, "return");
|
||||||
|
assert_equals(element.getAttribute(attribute), "return", "Return same string");
|
||||||
|
assert_equals(typeof element[attribute], "function", "Convert to function");
|
||||||
|
element.removeAttribute(attribute);
|
||||||
|
}, "Reflect " + interface + "." + attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testForwardToWindow(interface, attribute) {
|
||||||
|
test(function() {
|
||||||
|
var element = getObject(interface);
|
||||||
|
window[attribute] = null;
|
||||||
|
element.setAttribute(attribute, "return");
|
||||||
|
assert_equals(typeof window[attribute], "function", "Convert to function");
|
||||||
|
assert_equals(window[attribute], element[attribute], "Forward content attribute");
|
||||||
|
function nop() {}
|
||||||
|
element[attribute] = nop;
|
||||||
|
assert_equals(window[attribute], nop, "Forward IDL attribute");
|
||||||
|
window[attribute] = null;
|
||||||
|
}, "Forward " + interface + "." + attribute + " to Window");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object.propertyIsEnumerable cannot be used because it doesn't
|
||||||
|
// work with properties inherited through the prototype chain.
|
||||||
|
function getEnumerable(interface) {
|
||||||
|
var enumerable = {};
|
||||||
|
for (var attribute in getObject(interface)) {
|
||||||
|
enumerable[attribute] = true;
|
||||||
|
}
|
||||||
|
return enumerable;
|
||||||
|
}
|
||||||
|
|
||||||
|
var enumerableCache = {};
|
||||||
|
function testEnumerate(interface, attribute) {
|
||||||
|
if (!(interface in enumerableCache)) {
|
||||||
|
enumerableCache[interface] = getEnumerable(interface);
|
||||||
|
}
|
||||||
|
test(function() {
|
||||||
|
assert_true(enumerableCache[interface][attribute]);
|
||||||
|
}, "Enumerate " + interface + "." + attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
[
|
||||||
|
"onblur",
|
||||||
|
"onerror",
|
||||||
|
"onfocus",
|
||||||
|
"onload",
|
||||||
|
"onscroll",
|
||||||
|
"onresize"
|
||||||
|
].forEach(function(attribute) {
|
||||||
|
testSet("HTMLBodyElement", attribute);
|
||||||
|
testEnumerate("HTMLBodyElement", attribute);
|
||||||
|
testReflect("HTMLBodyElement", attribute);
|
||||||
|
testForwardToWindow("HTMLBodyElement", attribute);
|
||||||
|
testSet("HTMLFrameSetElement", attribute);
|
||||||
|
testEnumerate("HTMLFrameSetElement", attribute);
|
||||||
|
testReflect("HTMLFrameSetElement", attribute);
|
||||||
|
testForwardToWindow("HTMLFrameSetElement", attribute);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>CustomEvent</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var type = "foo";
|
||||||
|
|
||||||
|
var target = document.createElement("div");
|
||||||
|
target.addEventListener(type, this.step_func(function(evt) {
|
||||||
|
assert_equals(evt.type, type);
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
var fooEvent = document.createEvent("CustomEvent");
|
||||||
|
fooEvent.initEvent(type, true, true);
|
||||||
|
target.dispatchEvent(fooEvent);
|
||||||
|
}, "CustomEvent dispatching.");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("CustomEvent");
|
||||||
|
assert_throws_js(TypeError, function() {
|
||||||
|
e.initCustomEvent();
|
||||||
|
});
|
||||||
|
}, "First parameter to initCustomEvent should be mandatory.");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("CustomEvent");
|
||||||
|
e.initCustomEvent("foo");
|
||||||
|
assert_equals(e.type, "foo", "type");
|
||||||
|
assert_false(e.bubbles, "bubbles");
|
||||||
|
assert_false(e.cancelable, "cancelable");
|
||||||
|
assert_equals(e.detail, null, "detail");
|
||||||
|
}, "initCustomEvent's default parameter values.");
|
||||||
|
</script>
|
|
@ -0,0 +1,132 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Event.cancelBubble</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-cancelbubble">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="outer">
|
||||||
|
<div id="middle">
|
||||||
|
<div id="inner"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
test(function () {
|
||||||
|
// See https://dom.spec.whatwg.org/#stop-propagation-flag
|
||||||
|
var e = document.createEvent('Event');
|
||||||
|
assert_false(e.cancelBubble, "cancelBubble must be false after event creation.");
|
||||||
|
}, "cancelBubble must be false when an event is initially created.");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// See https://dom.spec.whatwg.org/#concept-event-initialize
|
||||||
|
|
||||||
|
// Event which bubbles.
|
||||||
|
var one = document.createEvent('Event');
|
||||||
|
one.cancelBubble = true;
|
||||||
|
one.initEvent('foo', true/*bubbles*/, false/*cancelable*/);
|
||||||
|
assert_false(one.cancelBubble, "initEvent() must set cancelBubble to false. [bubbles=true]");
|
||||||
|
// Re-initialization.
|
||||||
|
one.cancelBubble = true;
|
||||||
|
one.initEvent('foo', true/*bubbles*/, false/*cancelable*/);
|
||||||
|
assert_false(one.cancelBubble, "2nd initEvent() call must set cancelBubble to false. [bubbles=true]");
|
||||||
|
|
||||||
|
// Event which doesn't bubble.
|
||||||
|
var two = document.createEvent('Event');
|
||||||
|
two.cancelBubble = true;
|
||||||
|
two.initEvent('foo', false/*bubbles*/, false/*cancelable*/);
|
||||||
|
assert_false(two.cancelBubble, "initEvent() must set cancelBubble to false. [bubbles=false]");
|
||||||
|
// Re-initialization.
|
||||||
|
two.cancelBubble = true;
|
||||||
|
two.initEvent('foo', false/*bubbles*/, false/*cancelable*/);
|
||||||
|
assert_false(two.cancelBubble, "2nd initEvent() call must set cancelBubble to false. [bubbles=false]");
|
||||||
|
}, "Initializing an event must set cancelBubble to false.");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// See https://dom.spec.whatwg.org/#dom-event-stoppropagation
|
||||||
|
var e = document.createEvent('Event');
|
||||||
|
e.stopPropagation();
|
||||||
|
assert_true(e.cancelBubble, "stopPropagation() must set cancelBubble to true.");
|
||||||
|
}, "stopPropagation() must set cancelBubble to true.");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// See https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation
|
||||||
|
var e = document.createEvent('Event');
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
assert_true(e.cancelBubble, "stopImmediatePropagation() must set cancelBubble to true.");
|
||||||
|
}, "stopImmediatePropagation() must set cancelBubble to true.");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var one = document.createEvent('Event');
|
||||||
|
one.stopPropagation();
|
||||||
|
one.cancelBubble = false;
|
||||||
|
assert_true(one.cancelBubble, "cancelBubble must still be true after attempting to set it to false.");
|
||||||
|
}, "Event.cancelBubble=false must have no effect.");
|
||||||
|
|
||||||
|
test(function (t) {
|
||||||
|
var outer = document.getElementById('outer');
|
||||||
|
var middle = document.getElementById('middle');
|
||||||
|
var inner = document.getElementById('inner');
|
||||||
|
|
||||||
|
outer.addEventListener('barbaz', t.step_func(function () {
|
||||||
|
assert_unreached("Setting Event.cancelBubble=false after setting Event.cancelBubble=true should have no effect.");
|
||||||
|
}), false/*useCapture*/);
|
||||||
|
|
||||||
|
middle.addEventListener('barbaz', function (e) {
|
||||||
|
e.cancelBubble = true;// Stop propagation.
|
||||||
|
e.cancelBubble = false;// Should be a no-op.
|
||||||
|
}, false/*useCapture*/);
|
||||||
|
|
||||||
|
var barbazEvent = document.createEvent('Event');
|
||||||
|
barbazEvent.initEvent('barbaz', true/*bubbles*/, false/*cancelable*/);
|
||||||
|
inner.dispatchEvent(barbazEvent);
|
||||||
|
}, "Event.cancelBubble=false must have no effect during event propagation.");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
// See https://dom.spec.whatwg.org/#concept-event-dispatch
|
||||||
|
// "14. Unset event’s [...] stop propagation flag,"
|
||||||
|
var e = document.createEvent('Event');
|
||||||
|
e.initEvent('foobar', true/*bubbles*/, true/*cancelable*/);
|
||||||
|
document.body.addEventListener('foobar', function listener(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
document.body.dispatchEvent(e);
|
||||||
|
assert_false(e.cancelBubble, "cancelBubble must be false after an event has been dispatched.");
|
||||||
|
}, "cancelBubble must be false after an event has been dispatched.");
|
||||||
|
|
||||||
|
test(function (t) {
|
||||||
|
var outer = document.getElementById('outer');
|
||||||
|
var middle = document.getElementById('middle');
|
||||||
|
var inner = document.getElementById('inner');
|
||||||
|
|
||||||
|
var propagationStopper = function (e) {
|
||||||
|
e.cancelBubble = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bubble phase
|
||||||
|
middle.addEventListener('bar', propagationStopper, false/*useCapture*/);
|
||||||
|
outer.addEventListener('bar', t.step_func(function listenerOne() {
|
||||||
|
assert_unreached("Setting cancelBubble=true should stop the event from bubbling further.");
|
||||||
|
}), false/*useCapture*/);
|
||||||
|
|
||||||
|
var barEvent = document.createEvent('Event');
|
||||||
|
barEvent.initEvent('bar', true/*bubbles*/, false/*cancelable*/);
|
||||||
|
inner.dispatchEvent(barEvent);
|
||||||
|
|
||||||
|
// Capture phase
|
||||||
|
outer.addEventListener('qux', propagationStopper, true/*useCapture*/);
|
||||||
|
middle.addEventListener('qux', t.step_func(function listenerTwo() {
|
||||||
|
assert_unreached("Setting cancelBubble=true should stop the event from propagating further, including during the Capture Phase.");
|
||||||
|
}), true/*useCapture*/);
|
||||||
|
|
||||||
|
var quxEvent = document.createEvent('Event');
|
||||||
|
quxEvent.initEvent('qux', false/*bubbles*/, false/*cancelable*/);
|
||||||
|
inner.dispatchEvent(quxEvent);
|
||||||
|
}, "Event.cancelBubble=true must set the stop propagation flag.");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Event constants</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script src="../constants.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var objects;
|
||||||
|
setup(function() {
|
||||||
|
objects = [
|
||||||
|
[Event, "Event interface object"],
|
||||||
|
[Event.prototype, "Event prototype object"],
|
||||||
|
[document.createEvent("Event"), "Event object"],
|
||||||
|
[document.createEvent("CustomEvent"), "CustomEvent object"]
|
||||||
|
]
|
||||||
|
})
|
||||||
|
testConstants(objects, [
|
||||||
|
["NONE", 0],
|
||||||
|
["CAPTURING_PHASE", 1],
|
||||||
|
["AT_TARGET", 2],
|
||||||
|
["BUBBLING_PHASE", 3]
|
||||||
|
], "eventPhase")
|
||||||
|
</script>
|
|
@ -0,0 +1,120 @@
|
||||||
|
// META: title=Event constructors
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
assert_throws_js(
|
||||||
|
TypeError,
|
||||||
|
() => Event(""),
|
||||||
|
"Calling Event constructor without 'new' must throw")
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
assert_throws_js(TypeError, function() {
|
||||||
|
new Event()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var test_error = { name: "test" }
|
||||||
|
assert_throws_exactly(test_error, function() {
|
||||||
|
new Event({ toString: function() { throw test_error; } })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("")
|
||||||
|
assert_equals(ev.type, "")
|
||||||
|
assert_equals(ev.target, null)
|
||||||
|
assert_equals(ev.srcElement, null)
|
||||||
|
assert_equals(ev.currentTarget, null)
|
||||||
|
assert_equals(ev.eventPhase, Event.NONE)
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
assert_equals(ev.defaultPrevented, false)
|
||||||
|
assert_equals(ev.returnValue, true)
|
||||||
|
assert_equals(ev.isTrusted, false)
|
||||||
|
assert_true(ev.timeStamp > 0)
|
||||||
|
assert_true("initEvent" in ev)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("test")
|
||||||
|
assert_equals(ev.type, "test")
|
||||||
|
assert_equals(ev.target, null)
|
||||||
|
assert_equals(ev.srcElement, null)
|
||||||
|
assert_equals(ev.currentTarget, null)
|
||||||
|
assert_equals(ev.eventPhase, Event.NONE)
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
assert_equals(ev.defaultPrevented, false)
|
||||||
|
assert_equals(ev.returnValue, true)
|
||||||
|
assert_equals(ev.isTrusted, false)
|
||||||
|
assert_true(ev.timeStamp > 0)
|
||||||
|
assert_true("initEvent" in ev)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
assert_throws_js(TypeError, function() { Event("test") },
|
||||||
|
'Calling Event constructor without "new" must throw');
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("I am an event", { bubbles: true, cancelable: false})
|
||||||
|
assert_equals(ev.type, "I am an event")
|
||||||
|
assert_equals(ev.bubbles, true)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("@", { bubblesIGNORED: true, cancelable: true})
|
||||||
|
assert_equals(ev.type, "@")
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, true)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("@", { "bubbles\0IGNORED": true, cancelable: true})
|
||||||
|
assert_equals(ev.type, "@")
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, true)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("Xx", { cancelable: true})
|
||||||
|
assert_equals(ev.type, "Xx")
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, true)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("Xx", {})
|
||||||
|
assert_equals(ev.type, "Xx")
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("Xx", {bubbles: true, cancelable: false, sweet: "x"})
|
||||||
|
assert_equals(ev.type, "Xx")
|
||||||
|
assert_equals(ev.bubbles, true)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
assert_equals(ev.sweet, undefined)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var called = []
|
||||||
|
var ev = new Event("Xx", {
|
||||||
|
get cancelable() {
|
||||||
|
called.push("cancelable")
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
get bubbles() {
|
||||||
|
called.push("bubbles")
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
get sweet() {
|
||||||
|
called.push("sweet")
|
||||||
|
return "x"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
assert_array_equals(called, ["bubbles", "cancelable"])
|
||||||
|
assert_equals(ev.type, "Xx")
|
||||||
|
assert_equals(ev.bubbles, true)
|
||||||
|
assert_equals(ev.cancelable, false)
|
||||||
|
assert_equals(ev.sweet, undefined)
|
||||||
|
})
|
||||||
|
test(function() {
|
||||||
|
var ev = new CustomEvent("$", {detail: 54, sweet: "x", sweet2: "x", cancelable:true})
|
||||||
|
assert_equals(ev.type, "$")
|
||||||
|
assert_equals(ev.bubbles, false)
|
||||||
|
assert_equals(ev.cancelable, true)
|
||||||
|
assert_equals(ev.sweet, undefined)
|
||||||
|
assert_equals(ev.detail, 54)
|
||||||
|
})
|
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Event.defaultPrevented is not reset after dispatchEvent()</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);
|
||||||
|
assert_equals(evt.srcElement, TARGET);
|
||||||
|
}, "Default prevention via preventDefault");
|
||||||
|
|
||||||
|
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.returnValue = false;
|
||||||
|
assert_true(e.defaultPrevented, "during dispatch");
|
||||||
|
}), true);
|
||||||
|
TARGET.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_true(evt.defaultPrevented, "after dispatch");
|
||||||
|
assert_equals(evt.target, TARGET);
|
||||||
|
assert_equals(evt.srcElement, TARGET);
|
||||||
|
}, "Default prevention via returnValue");
|
||||||
|
</script>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Event.defaultPrevented</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var ev;
|
||||||
|
test(function() {
|
||||||
|
ev = document.createEvent("Event");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "When an event is created, defaultPrevented should be initialized to false.");
|
||||||
|
test(function() {
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
assert_equals(ev.bubbles, true, "bubbles");
|
||||||
|
assert_equals(ev.cancelable, false, "cancelable");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "initEvent should work correctly (not cancelable).");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(ev.cancelable, false, "cancelable (before)");
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_equals(ev.cancelable, false, "cancelable (after)");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "preventDefault() should not change defaultPrevented if cancelable is false.");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(ev.cancelable, false, "cancelable (before)");
|
||||||
|
ev.returnValue = false;
|
||||||
|
assert_equals(ev.cancelable, false, "cancelable (after)");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "returnValue should not change defaultPrevented if cancelable is false.");
|
||||||
|
test(function() {
|
||||||
|
ev.initEvent("foo", true, true);
|
||||||
|
assert_equals(ev.bubbles, true, "bubbles");
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "initEvent should work correctly (cancelable).");
|
||||||
|
test(function() {
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable (before)");
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable (after)");
|
||||||
|
assert_equals(ev.defaultPrevented, true, "defaultPrevented");
|
||||||
|
}, "preventDefault() should change defaultPrevented if cancelable is true.");
|
||||||
|
test(function() {
|
||||||
|
ev.initEvent("foo", true, true);
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable (before)");
|
||||||
|
ev.returnValue = false;
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable (after)");
|
||||||
|
assert_equals(ev.defaultPrevented, true, "defaultPrevented");
|
||||||
|
}, "returnValue should change defaultPrevented if cancelable is true.");
|
||||||
|
test(function() {
|
||||||
|
ev.initEvent("foo", true, true);
|
||||||
|
assert_equals(ev.bubbles, true, "bubbles");
|
||||||
|
assert_equals(ev.cancelable, true, "cancelable");
|
||||||
|
assert_equals(ev.defaultPrevented, false, "defaultPrevented");
|
||||||
|
}, "initEvent should unset defaultPrevented.");
|
||||||
|
</script>
|
|
@ -0,0 +1,59 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Setting cancelBubble=true prior to dispatchEvent()</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var current_targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = [];
|
||||||
|
var actual_targets = [];
|
||||||
|
var expected_phases = [];
|
||||||
|
var actual_phases = [];
|
||||||
|
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < current_targets.length; ++i) {
|
||||||
|
current_targets[i].addEventListener(event, test_event, true);
|
||||||
|
current_targets[i].addEventListener(event, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event, true, true);
|
||||||
|
evt.cancelBubble = true;
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "actual_targets");
|
||||||
|
assert_array_equals(actual_phases, expected_phases, "actual_phases");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,98 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Event.bubbles attribute is set to false </title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
function targetsForDocumentChain(document) {
|
||||||
|
return [
|
||||||
|
document,
|
||||||
|
document.documentElement,
|
||||||
|
document.getElementsByTagName("body")[0],
|
||||||
|
document.getElementById("table"),
|
||||||
|
document.getElementById("table-body"),
|
||||||
|
document.getElementById("parent")
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function testChain(document, targetParents, phases, event_type) {
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var targets = targetParents.concat(target);
|
||||||
|
var expected_targets = targets.concat(target);
|
||||||
|
|
||||||
|
var actual_targets = [], actual_phases = [];
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].addEventListener(event_type, test_event, true);
|
||||||
|
targets[i].addEventListener(event_type, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, false, true);
|
||||||
|
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "targets");
|
||||||
|
assert_array_equals(actual_phases, phases, "phases");
|
||||||
|
}
|
||||||
|
|
||||||
|
var phasesForDocumentChain = [
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
];
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var chainWithWindow = [window].concat(targetsForDocumentChain(document));
|
||||||
|
testChain(
|
||||||
|
document, chainWithWindow, [Event.CAPTURING_PHASE].concat(phasesForDocumentChain), "click");
|
||||||
|
}, "In window.document with click event");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
testChain(document, targetsForDocumentChain(document), phasesForDocumentChain, "load");
|
||||||
|
}, "In window.document with load event")
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var documentClone = document.cloneNode(true);
|
||||||
|
testChain(
|
||||||
|
documentClone, targetsForDocumentChain(documentClone), phasesForDocumentChain, "click");
|
||||||
|
}, "In window.document.cloneNode(true)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var newDocument = new Document();
|
||||||
|
newDocument.appendChild(document.documentElement.cloneNode(true));
|
||||||
|
testChain(
|
||||||
|
newDocument, targetsForDocumentChain(newDocument), phasesForDocumentChain, "click");
|
||||||
|
}, "In new Document()");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var HTMLDocument = document.implementation.createHTMLDocument();
|
||||||
|
HTMLDocument.body.appendChild(document.getElementById("table").cloneNode(true));
|
||||||
|
testChain(
|
||||||
|
HTMLDocument, targetsForDocumentChain(HTMLDocument), phasesForDocumentChain, "click");
|
||||||
|
}, "In DOMImplementation.createHTMLDocument()");
|
||||||
|
</script>
|
|
@ -0,0 +1,108 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Event.bubbles attribute is set to false </title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
function concatReverse(a) {
|
||||||
|
return a.concat(a.map(function(x) { return x }).reverse());
|
||||||
|
}
|
||||||
|
|
||||||
|
function targetsForDocumentChain(document) {
|
||||||
|
return [
|
||||||
|
document,
|
||||||
|
document.documentElement,
|
||||||
|
document.getElementsByTagName("body")[0],
|
||||||
|
document.getElementById("table"),
|
||||||
|
document.getElementById("table-body"),
|
||||||
|
document.getElementById("parent")
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function testChain(document, targetParents, phases, event_type) {
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var targets = targetParents.concat(target);
|
||||||
|
var expected_targets = concatReverse(targets);
|
||||||
|
|
||||||
|
var actual_targets = [], actual_phases = [];
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].addEventListener(event_type, test_event, true);
|
||||||
|
targets[i].addEventListener(event_type, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "targets");
|
||||||
|
assert_array_equals(actual_phases, phases, "phases");
|
||||||
|
}
|
||||||
|
|
||||||
|
var phasesForDocumentChain = [
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
];
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var chainWithWindow = [window].concat(targetsForDocumentChain(document));
|
||||||
|
var phases = [Event.CAPTURING_PHASE].concat(phasesForDocumentChain, Event.BUBBLING_PHASE);
|
||||||
|
testChain(document, chainWithWindow, phases, "click");
|
||||||
|
}, "In window.document with click event");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
testChain(document, targetsForDocumentChain(document), phasesForDocumentChain, "load");
|
||||||
|
}, "In window.document with load event")
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var documentClone = document.cloneNode(true);
|
||||||
|
testChain(
|
||||||
|
documentClone, targetsForDocumentChain(documentClone), phasesForDocumentChain, "click");
|
||||||
|
}, "In window.document.cloneNode(true)");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var newDocument = new Document();
|
||||||
|
newDocument.appendChild(document.documentElement.cloneNode(true));
|
||||||
|
testChain(
|
||||||
|
newDocument, targetsForDocumentChain(newDocument), phasesForDocumentChain, "click");
|
||||||
|
}, "In new Document()");
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
var HTMLDocument = document.implementation.createHTMLDocument();
|
||||||
|
HTMLDocument.body.appendChild(document.getElementById("table").cloneNode(true));
|
||||||
|
testChain(
|
||||||
|
HTMLDocument, targetsForDocumentChain(HTMLDocument), phasesForDocumentChain, "click");
|
||||||
|
}, "In DOMImplementation.createHTMLDocument()");
|
||||||
|
</script>
|
|
@ -0,0 +1,425 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Synthetic click event "magic"</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<div id=dump style=display:none></div>
|
||||||
|
<script>
|
||||||
|
var dump = document.getElementById("dump")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_true(input.checked)
|
||||||
|
})
|
||||||
|
input.click()
|
||||||
|
}, "basic with click()")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_true(input.checked)
|
||||||
|
})
|
||||||
|
input.dispatchEvent(new MouseEvent("click", {bubbles:true})) // equivalent to the above
|
||||||
|
}, "basic with dispatchEvent()")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_false(input.checked)
|
||||||
|
})
|
||||||
|
input.dispatchEvent(new Event("click", {bubbles:true})) // no MouseEvent
|
||||||
|
}, "basic with wrong event class")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
var child = input.appendChild(new Text("does not matter"))
|
||||||
|
child.dispatchEvent(new MouseEvent("click")) // does not bubble
|
||||||
|
assert_false(input.checked)
|
||||||
|
t.done()
|
||||||
|
}, "look at parents only when event bubbles")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_true(input.checked)
|
||||||
|
})
|
||||||
|
var child = input.appendChild(new Text("does not matter"))
|
||||||
|
child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
|
||||||
|
}, "look at parents when event bubbles")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func(function() {
|
||||||
|
assert_false(input.checked, "input pre-click must not be triggered")
|
||||||
|
})
|
||||||
|
var child = input.appendChild(document.createElement("input"))
|
||||||
|
child.type = "checkbox"
|
||||||
|
child.onclick = t.step_func(function() {
|
||||||
|
assert_true(child.checked, "child pre-click must be triggered")
|
||||||
|
})
|
||||||
|
child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
|
||||||
|
t.done()
|
||||||
|
}, "pick the first with activation behavior <input type=checkbox>")
|
||||||
|
|
||||||
|
async_test(function(t) { // as above with <a>
|
||||||
|
window.hrefComplete = t.step_func(function(a) {
|
||||||
|
assert_equals(a, 'child');
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
var link = document.createElement("a")
|
||||||
|
link.href = "javascript:hrefComplete('link')" // must not be triggered
|
||||||
|
dump.appendChild(link)
|
||||||
|
var child = link.appendChild(document.createElement("a"))
|
||||||
|
child.href = "javascript:hrefComplete('child')"
|
||||||
|
child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
|
||||||
|
}, "pick the first with activation behavior <a href>")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "radio"
|
||||||
|
dump.appendChild(input)
|
||||||
|
input.onclick = t.step_func(function() {
|
||||||
|
assert_false(input.checked, "input pre-click must not be triggered")
|
||||||
|
})
|
||||||
|
var child = input.appendChild(document.createElement("input"))
|
||||||
|
child.type = "radio"
|
||||||
|
child.onclick = t.step_func(function() {
|
||||||
|
assert_true(child.checked, "child pre-click must be triggered")
|
||||||
|
})
|
||||||
|
child.dispatchEvent(new MouseEvent("click", {bubbles:true}))
|
||||||
|
t.done()
|
||||||
|
}, "pick the first with activation behavior <input type=radio>")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
var clickEvent = new MouseEvent("click")
|
||||||
|
input.onchange = t.step_func_done(function() {
|
||||||
|
assert_false(clickEvent.defaultPrevented)
|
||||||
|
assert_true(clickEvent.returnValue)
|
||||||
|
assert_equals(clickEvent.eventPhase, 0)
|
||||||
|
assert_equals(clickEvent.currentTarget, null)
|
||||||
|
assert_equals(clickEvent.target, input)
|
||||||
|
assert_equals(clickEvent.srcElement, input)
|
||||||
|
assert_equals(clickEvent.composedPath().length, 0)
|
||||||
|
})
|
||||||
|
input.dispatchEvent(clickEvent)
|
||||||
|
}, "event state during post-click handling")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
var clickEvent = new MouseEvent("click")
|
||||||
|
var finalTarget = document.createElement("doesnotmatter")
|
||||||
|
finalTarget.onclick = t.step_func_done(function() {
|
||||||
|
assert_equals(clickEvent.target, finalTarget)
|
||||||
|
assert_equals(clickEvent.srcElement, finalTarget)
|
||||||
|
})
|
||||||
|
input.onchange = t.step_func(function() {
|
||||||
|
finalTarget.dispatchEvent(clickEvent)
|
||||||
|
})
|
||||||
|
input.dispatchEvent(clickEvent)
|
||||||
|
}, "redispatch during post-click handling")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
dump.appendChild(input)
|
||||||
|
var child = input.appendChild(document.createElement("input"))
|
||||||
|
child.type = "checkbox"
|
||||||
|
child.disabled = true
|
||||||
|
child.click()
|
||||||
|
assert_false(input.checked)
|
||||||
|
assert_false(child.checked)
|
||||||
|
t.done()
|
||||||
|
}, "disabled checkbox still has activation behavior")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var state = "start"
|
||||||
|
|
||||||
|
var form = document.createElement("form")
|
||||||
|
form.onsubmit = t.step_func(() => {
|
||||||
|
if(state == "start" || state == "checkbox") {
|
||||||
|
state = "failure"
|
||||||
|
} else if(state == "form") {
|
||||||
|
state = "done"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
dump.appendChild(form)
|
||||||
|
var button = form.appendChild(document.createElement("button"))
|
||||||
|
button.type = "submit"
|
||||||
|
var checkbox = button.appendChild(document.createElement("input"))
|
||||||
|
checkbox.type = "checkbox"
|
||||||
|
checkbox.onclick = t.step_func(() => {
|
||||||
|
if(state == "start") {
|
||||||
|
assert_unreached()
|
||||||
|
} else if(state == "checkbox") {
|
||||||
|
assert_true(checkbox.checked)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
checkbox.disabled = true
|
||||||
|
checkbox.click()
|
||||||
|
assert_equals(state, "start")
|
||||||
|
|
||||||
|
state = "checkbox"
|
||||||
|
checkbox.disabled = false
|
||||||
|
checkbox.click()
|
||||||
|
assert_equals(state, "checkbox")
|
||||||
|
|
||||||
|
state = "form"
|
||||||
|
button.click()
|
||||||
|
assert_equals(state, "done")
|
||||||
|
|
||||||
|
t.done()
|
||||||
|
}, "disabled checkbox still has activation behavior, part 2")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var state = "start"
|
||||||
|
|
||||||
|
var form = document.createElement("form")
|
||||||
|
form.onsubmit = t.step_func(() => {
|
||||||
|
if(state == "start" || state == "radio") {
|
||||||
|
state = "failure"
|
||||||
|
} else if(state == "form") {
|
||||||
|
state = "done"
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
dump.appendChild(form)
|
||||||
|
var button = form.appendChild(document.createElement("button"))
|
||||||
|
button.type = "submit"
|
||||||
|
var radio = button.appendChild(document.createElement("input"))
|
||||||
|
radio.type = "radio"
|
||||||
|
radio.onclick = t.step_func(() => {
|
||||||
|
if(state == "start") {
|
||||||
|
assert_unreached()
|
||||||
|
} else if(state == "radio") {
|
||||||
|
assert_true(radio.checked)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
radio.disabled = true
|
||||||
|
radio.click()
|
||||||
|
assert_equals(state, "start")
|
||||||
|
|
||||||
|
state = "radio"
|
||||||
|
radio.disabled = false
|
||||||
|
radio.click()
|
||||||
|
assert_equals(state, "radio")
|
||||||
|
|
||||||
|
state = "form"
|
||||||
|
button.click()
|
||||||
|
assert_equals(state, "done")
|
||||||
|
|
||||||
|
t.done()
|
||||||
|
}, "disabled radio still has activation behavior")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "checkbox"
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_true(input.checked)
|
||||||
|
})
|
||||||
|
input.click()
|
||||||
|
}, "disconnected checkbox should be checked")
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var input = document.createElement("input")
|
||||||
|
input.type = "radio"
|
||||||
|
input.onclick = t.step_func_done(function() {
|
||||||
|
assert_true(input.checked)
|
||||||
|
})
|
||||||
|
input.click()
|
||||||
|
}, "disconnected radio should be checked")
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
input.onclick = t.step_func_done(() => {
|
||||||
|
assert_true(input.checked);
|
||||||
|
});
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
}, `disconnected checkbox should be checked from dispatchEvent(new MouseEvent('click'))`);
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
input.onclick = t.step_func_done(() => {
|
||||||
|
assert_true(input.checked);
|
||||||
|
});
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
}, `disconnected radio should be checked from dispatchEvent(new MouseEvent('click'))`);
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
input.dispatchEvent(new MouseEvent("click"));
|
||||||
|
assert_true(input.checked);
|
||||||
|
}, `disabled checkbox should be checked from dispatchEvent(new MouseEvent("click"))`);
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
input.dispatchEvent(new MouseEvent("click"));
|
||||||
|
assert_true(input.checked);
|
||||||
|
}, `disabled radio should be checked from dispatchEvent(new MouseEvent("click"))`);
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
input.onclick = t.step_func_done();
|
||||||
|
input.dispatchEvent(new MouseEvent("click"));
|
||||||
|
}, `disabled checkbox should fire onclick`);
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
input.onclick = t.step_func_done();
|
||||||
|
input.dispatchEvent(new MouseEvent("click"));
|
||||||
|
}, `disabled radio should fire onclick`);
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
input.onclick = t.step_func(ev => {
|
||||||
|
assert_true(input.checked);
|
||||||
|
ev.preventDefault();
|
||||||
|
queueMicrotask(t.step_func_done(() => {
|
||||||
|
assert_false(input.checked);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
}, `disabled checkbox should get legacy-canceled-activation behavior`);
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
input.onclick = t.step_func(ev => {
|
||||||
|
assert_true(input.checked);
|
||||||
|
ev.preventDefault();
|
||||||
|
queueMicrotask(t.step_func_done(() => {
|
||||||
|
assert_false(input.checked);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
}, `disabled radio should get legacy-canceled-activation behavior`);
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
const ev = new MouseEvent("click", { cancelable: true });
|
||||||
|
ev.preventDefault();
|
||||||
|
input.dispatchEvent(ev);
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, `disabled checkbox should get legacy-canceled-activation behavior 2`);
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
const ev = new MouseEvent("click", { cancelable: true });
|
||||||
|
ev.preventDefault();
|
||||||
|
input.dispatchEvent(ev);
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, `disabled radio should get legacy-canceled-activation behavior 2`);
|
||||||
|
|
||||||
|
for (const type of ["checkbox", "radio"]) {
|
||||||
|
for (const handler of ["oninput", "onchange"]) {
|
||||||
|
async_test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = type;
|
||||||
|
input.onclick = t.step_func(ev => {
|
||||||
|
input.disabled = true;
|
||||||
|
});
|
||||||
|
input[handler] = t.step_func(ev => {
|
||||||
|
assert_equals(input.checked, true);
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
dump.append(input);
|
||||||
|
input.click();
|
||||||
|
}, `disabling ${type} in onclick listener shouldn't suppress ${handler}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
var form = document.createElement("form")
|
||||||
|
var didSubmit = false
|
||||||
|
form.onsubmit = t.step_func(() => {
|
||||||
|
didSubmit = true
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
var input = form.appendChild(document.createElement("input"))
|
||||||
|
input.type = "submit"
|
||||||
|
input.click()
|
||||||
|
assert_false(didSubmit)
|
||||||
|
t.done()
|
||||||
|
}, "disconnected form should not submit")
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const form = document.createElement("form");
|
||||||
|
form.onsubmit = t.step_func(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_unreached("The form is unexpectedly submitted.");
|
||||||
|
});
|
||||||
|
dump.append(form);
|
||||||
|
const input = form.appendChild(document.createElement("input"));
|
||||||
|
input.type = "submit"
|
||||||
|
input.disabled = true;
|
||||||
|
input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
t.done();
|
||||||
|
}, "disabled submit button should not activate");
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const form = document.createElement("form");
|
||||||
|
form.onsubmit = t.step_func(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_unreached("The form is unexpectedly submitted.");
|
||||||
|
});
|
||||||
|
dump.append(form);
|
||||||
|
const input = form.appendChild(document.createElement("input"));
|
||||||
|
input.onclick = t.step_func(() => {
|
||||||
|
input.disabled = true;
|
||||||
|
});
|
||||||
|
input.type = "submit"
|
||||||
|
input.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
t.done();
|
||||||
|
}, "submit button should not activate if the event listener disables it");
|
||||||
|
|
||||||
|
async_test(t => {
|
||||||
|
const form = document.createElement("form");
|
||||||
|
form.onsubmit = t.step_func(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_unreached("The form is unexpectedly submitted.");
|
||||||
|
});
|
||||||
|
dump.append(form);
|
||||||
|
const input = form.appendChild(document.createElement("input"));
|
||||||
|
input.onclick = t.step_func(() => {
|
||||||
|
input.type = "submit"
|
||||||
|
input.disabled = true;
|
||||||
|
});
|
||||||
|
input.click();
|
||||||
|
t.done();
|
||||||
|
}, "submit button that morphed from checkbox should not activate");
|
||||||
|
</script>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Clicks on input element</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=dump style=display:none></div>
|
||||||
|
<script>
|
||||||
|
var dump = document.getElementById("dump")
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.append(input);
|
||||||
|
dump.append(label);
|
||||||
|
label.click();
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, "disabled checkbox should not be checked from label click");
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.append(input);
|
||||||
|
dump.append(label);
|
||||||
|
label.click();
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, "disabled radio should not be checked from label click");
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.disabled = true;
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.append(input);
|
||||||
|
dump.append(label);
|
||||||
|
label.dispatchEvent(new MouseEvent("click"));
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, "disabled checkbox should not be checked from label click by dispatchEvent");
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "radio";
|
||||||
|
input.disabled = true;
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.append(input);
|
||||||
|
dump.append(label);
|
||||||
|
label.dispatchEvent(new MouseEvent("click"));
|
||||||
|
assert_false(input.checked);
|
||||||
|
}, "disabled radio should not be checked from label click by dispatchEvent");
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const checkbox = dump.appendChild(document.createElement("input"));
|
||||||
|
checkbox.type = "checkbox";
|
||||||
|
checkbox.onclick = ev => {
|
||||||
|
checkbox.type = "date";
|
||||||
|
ev.preventDefault();
|
||||||
|
};
|
||||||
|
checkbox.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
assert_false(checkbox.checked);
|
||||||
|
}, "checkbox morphed into another type should not mutate checked state");
|
||||||
|
|
||||||
|
test(t => {
|
||||||
|
const radio1 = dump.appendChild(document.createElement("input"));
|
||||||
|
const radio2 = dump.appendChild(radio1.cloneNode());
|
||||||
|
radio1.type = radio2.type = "radio";
|
||||||
|
radio1.name = radio2.name = "foo";
|
||||||
|
radio2.checked = true;
|
||||||
|
radio1.onclick = ev => {
|
||||||
|
radio1.type = "date";
|
||||||
|
ev.preventDefault();
|
||||||
|
};
|
||||||
|
radio1.dispatchEvent(new MouseEvent("click", { cancelable: true }));
|
||||||
|
assert_false(radio1.checked);
|
||||||
|
assert_true(radio2.checked);
|
||||||
|
}, "radio morphed into another type should not steal the existing checked state");
|
||||||
|
</script>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Click event on an element not in the document</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var EVENT = "click";
|
||||||
|
var TARGET = document.createElement("somerandomelement");
|
||||||
|
var t = async_test("Click event can be dispatched to an element that is not in the document.")
|
||||||
|
TARGET.addEventListener(EVENT, t.step_func(function(evt) {
|
||||||
|
assert_equals(evt.target, TARGET);
|
||||||
|
assert_equals(evt.srcElement, TARGET);
|
||||||
|
t.done();
|
||||||
|
}), true);
|
||||||
|
var e = document.createEvent("Event");
|
||||||
|
e.initEvent(EVENT, true, true);
|
||||||
|
TARGET.dispatchEvent(e);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,190 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
|
||||||
|
<title>input and change events for detached checkbox and radio elements</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_false(inputEventFired);
|
||||||
|
assert_false(changeEventFired);
|
||||||
|
}, 'detached checkbox should not emit input or change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_false(inputEventFired);
|
||||||
|
assert_false(changeEventFired);
|
||||||
|
}, 'detached radio should not emit input or change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_false(inputEventFired);
|
||||||
|
assert_false(changeEventFired);
|
||||||
|
}, `detached checkbox should not emit input or change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_false(inputEventFired);
|
||||||
|
assert_false(changeEventFired);
|
||||||
|
}, `detached radio should not emit input or change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
document.body.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, 'attached checkbox should emit input and change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
document.body.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, 'attached radio should emit input and change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
document.body.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, `attached checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
document.body.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, `attached radio should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
const shadowHost = document.createElement('div');
|
||||||
|
document.body.appendChild(shadowHost);
|
||||||
|
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
|
||||||
|
shadowRoot.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, 'attached to shadow dom checkbox should emit input and change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
const shadowHost = document.createElement('div');
|
||||||
|
document.body.appendChild(shadowHost);
|
||||||
|
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
|
||||||
|
shadowRoot.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.click();
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, 'attached to shadow dom radio should emit input and change events on click().');
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'checkbox';
|
||||||
|
const shadowHost = document.createElement('div');
|
||||||
|
document.body.appendChild(shadowHost);
|
||||||
|
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
|
||||||
|
shadowRoot.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, `attached to shadow dom checkbox should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const input = document.createElement('input');
|
||||||
|
input.type = 'radio';
|
||||||
|
const shadowHost = document.createElement('div');
|
||||||
|
document.body.appendChild(shadowHost);
|
||||||
|
const shadowRoot = shadowHost.attachShadow({mode: 'open'});
|
||||||
|
shadowRoot.appendChild(input);
|
||||||
|
|
||||||
|
let inputEventFired = false;
|
||||||
|
input.addEventListener('input', () => inputEventFired = true);
|
||||||
|
let changeEventFired = false;
|
||||||
|
input.addEventListener('change', () => changeEventFired = true);
|
||||||
|
input.dispatchEvent(new MouseEvent('click'));
|
||||||
|
assert_true(inputEventFired);
|
||||||
|
assert_true(changeEventFired);
|
||||||
|
}, `attached to shadow dom radio should emit input and change events on dispatchEvent(new MouseEvent('click')).`);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Dispatch additional events inside an event listener </title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "bar";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = [
|
||||||
|
window,
|
||||||
|
document,
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
table,
|
||||||
|
tbody,
|
||||||
|
parent,
|
||||||
|
target,
|
||||||
|
target,
|
||||||
|
target, // The additional listener for target runs as we copy its listeners twice
|
||||||
|
parent,
|
||||||
|
tbody,
|
||||||
|
table,
|
||||||
|
body,
|
||||||
|
html,
|
||||||
|
document,
|
||||||
|
window
|
||||||
|
];
|
||||||
|
var expected_listeners = [0,0,0,0,0,0,0,0,1,3,1,1,1,1,1,1,1];
|
||||||
|
|
||||||
|
var actual_targets = [], actual_listeners = [];
|
||||||
|
var test_event_function = function(i) {
|
||||||
|
return this.step_func(function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_listeners.push(i);
|
||||||
|
|
||||||
|
if (evt.eventPhase != evt.BUBBLING_PHASE && evt.currentTarget.foo != 1) {
|
||||||
|
evt.currentTarget.removeEventListener(event_type, event_handlers[0], true);
|
||||||
|
evt.currentTarget.addEventListener(event_type, event_handlers[2], true);
|
||||||
|
evt.currentTarget.foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evt.eventPhase != evt.CAPTURING_PHASE && evt.currentTarget.foo != 3) {
|
||||||
|
evt.currentTarget.removeEventListener(event_type, event_handlers[0], false);
|
||||||
|
evt.currentTarget.addEventListener(event_type, event_handlers[3], false);
|
||||||
|
evt.currentTarget.foo = 3;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}.bind(this);
|
||||||
|
var event_handlers = [
|
||||||
|
test_event_function(0),
|
||||||
|
test_event_function(1),
|
||||||
|
test_event_function(2),
|
||||||
|
test_event_function(3),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; ++i) {
|
||||||
|
targets[i].addEventListener(event_type, event_handlers[0], true);
|
||||||
|
targets[i].addEventListener(event_type, event_handlers[1], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "actual_targets");
|
||||||
|
assert_array_equals(actual_listeners, expected_listeners, "actual_listeners");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,20 @@
|
||||||
|
test(t => {
|
||||||
|
const hostParent = document.createElement("section"),
|
||||||
|
host = hostParent.appendChild(document.createElement("div")),
|
||||||
|
shadowRoot = host.attachShadow({ mode: "closed" }),
|
||||||
|
targetParent = shadowRoot.appendChild(document.createElement("p")),
|
||||||
|
target = targetParent.appendChild(document.createElement("span")),
|
||||||
|
path = [hostParent, host, shadowRoot, targetParent, target],
|
||||||
|
expected = [],
|
||||||
|
result = [];
|
||||||
|
path.forEach((node, index) => {
|
||||||
|
expected.splice(index, 0, "capturing " + node.nodeName);
|
||||||
|
expected.splice(index + 1, 0, "bubbling " + node.nodeName);
|
||||||
|
});
|
||||||
|
path.forEach(node => {
|
||||||
|
node.addEventListener("test", () => { result.push("bubbling " + node.nodeName) });
|
||||||
|
node.addEventListener("test", () => { result.push("capturing " + node.nodeName) }, true);
|
||||||
|
});
|
||||||
|
target.dispatchEvent(new CustomEvent('test', { detail: {}, bubbles: true, composed: true }));
|
||||||
|
assert_array_equals(result, expected);
|
||||||
|
});
|
|
@ -0,0 +1,51 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Multiple dispatchEvent() and cancelBubble</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=log></div>
|
||||||
|
|
||||||
|
<div id="parent" style="display: none">
|
||||||
|
<input id="target" type="hidden" value=""/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var actual_result;
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_result.push(evt.currentTarget);
|
||||||
|
|
||||||
|
if (parent == evt.currentTarget) {
|
||||||
|
evt.cancelBubble = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
|
||||||
|
target.addEventListener(event_type, test_event, false);
|
||||||
|
parent.addEventListener(event_type, test_event, false);
|
||||||
|
document.addEventListener(event_type, test_event, false);
|
||||||
|
window.addEventListener(event_type, test_event, false);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [target, parent]);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
parent.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [parent]);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
document.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [document, window]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,51 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title> Multiple dispatchEvent() and stopPropagation() </title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=log></div>
|
||||||
|
|
||||||
|
<div id="parent" style="display: none">
|
||||||
|
<input id="target" type="hidden" value=""/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var actual_result;
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_result.push(evt.currentTarget);
|
||||||
|
|
||||||
|
if (parent == evt.currentTarget) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
|
||||||
|
target.addEventListener(event_type, test_event, false);
|
||||||
|
parent.addEventListener(event_type, test_event, false);
|
||||||
|
document.addEventListener(event_type, test_event, false);
|
||||||
|
window.addEventListener(event_type, test_event, false);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [target, parent]);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
parent.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [parent]);
|
||||||
|
|
||||||
|
actual_result = [];
|
||||||
|
document.dispatchEvent(evt);
|
||||||
|
assert_array_equals(actual_result, [document, window]);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,70 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>EventTarget.addEventListener: capture argument omitted</title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var targets = [
|
||||||
|
target,
|
||||||
|
document.getElementById("parent"),
|
||||||
|
document.getElementById("table-body"),
|
||||||
|
document.getElementById("table"),
|
||||||
|
document.body,
|
||||||
|
document.documentElement,
|
||||||
|
document,
|
||||||
|
window
|
||||||
|
];
|
||||||
|
var phases = [
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE
|
||||||
|
];
|
||||||
|
|
||||||
|
var actual_targets = [], actual_phases = [];
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].addEventListener(event_type, test_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].removeEventListener(event_type, test_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, targets, "targets");
|
||||||
|
assert_array_equals(actual_phases, phases, "phases");
|
||||||
|
}, "EventTarget.addEventListener with the capture argument omitted");
|
||||||
|
</script>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Listeners are invoked in correct order (AT_TARGET phase)</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
const expectedOrder = ["capturing", "bubbling"];
|
||||||
|
|
||||||
|
let actualOrder = [];
|
||||||
|
el.addEventListener("click", evt => {
|
||||||
|
assert_equals(evt.eventPhase, Event.AT_TARGET);
|
||||||
|
actualOrder.push("bubbling");
|
||||||
|
}, false);
|
||||||
|
el.addEventListener("click", evt => {
|
||||||
|
assert_equals(evt.eventPhase, Event.AT_TARGET);
|
||||||
|
actualOrder.push("capturing");
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
el.dispatchEvent(new Event("click", {bubbles: true}));
|
||||||
|
assert_array_equals(actualOrder, expectedOrder, "bubbles: true");
|
||||||
|
|
||||||
|
actualOrder = [];
|
||||||
|
el.dispatchEvent(new Event("click", {bubbles: false}));
|
||||||
|
assert_array_equals(actualOrder, expectedOrder, "bubbles: false");
|
||||||
|
}, "Listeners are invoked in correct order (AT_TARGET phase)");
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Event phases order</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
async_test(function() {
|
||||||
|
document.addEventListener('DOMContentLoaded', this.step_func_done(function() {
|
||||||
|
var parent = document.getElementById('parent');
|
||||||
|
var child = document.getElementById('child');
|
||||||
|
|
||||||
|
var order = [];
|
||||||
|
|
||||||
|
parent.addEventListener('click', this.step_func(function(){ order.push(1) }), true);
|
||||||
|
child.addEventListener('click', this.step_func(function(){ order.push(2) }), false);
|
||||||
|
parent.addEventListener('click', this.step_func(function(){ order.push(3) }), false);
|
||||||
|
|
||||||
|
child.dispatchEvent(new Event('click', {bubbles: true}));
|
||||||
|
|
||||||
|
assert_array_equals(order, [1, 2, 3]);
|
||||||
|
}));
|
||||||
|
}, "Event phases order");
|
||||||
|
</script>
|
||||||
|
<div id="parent">
|
||||||
|
<div id="child"></div>
|
||||||
|
</div>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Custom event on an element in another document</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var doc = document.implementation.createHTMLDocument("Demo");
|
||||||
|
var element = doc.createElement("div");
|
||||||
|
var called = false;
|
||||||
|
element.addEventListener("foo", this.step_func(function(ev) {
|
||||||
|
assert_false(called);
|
||||||
|
called = true;
|
||||||
|
assert_equals(ev.target, element);
|
||||||
|
assert_equals(ev.srcElement, element);
|
||||||
|
}));
|
||||||
|
doc.body.appendChild(element);
|
||||||
|
|
||||||
|
var event = new Event("foo");
|
||||||
|
element.dispatchEvent(event);
|
||||||
|
assert_true(called);
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,59 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title> Calling stopPropagation() prior to dispatchEvent() </title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=log></div>
|
||||||
|
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var current_targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = [];
|
||||||
|
var actual_targets = [];
|
||||||
|
var expected_phases = [];
|
||||||
|
var actual_phases = [];
|
||||||
|
|
||||||
|
var test_event = function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < current_targets.length; ++i) {
|
||||||
|
current_targets[i].addEventListener(event, test_event, true);
|
||||||
|
current_targets[i].addEventListener(event, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event, true, true);
|
||||||
|
evt.stopPropagation();
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "actual_targets");
|
||||||
|
assert_array_equals(actual_phases, expected_phases, "actual_phases");
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,66 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Dispatch additional events inside an event listener </title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = [
|
||||||
|
window, document, html, body, table,
|
||||||
|
target, parent, tbody,
|
||||||
|
table, body, html, document, window,
|
||||||
|
tbody, parent, target];
|
||||||
|
var actual_targets = [];
|
||||||
|
var expected_types = [
|
||||||
|
"foo", "foo", "foo", "foo", "foo",
|
||||||
|
"bar", "bar", "bar",
|
||||||
|
"bar", "bar", "bar", "bar", "bar",
|
||||||
|
"foo", "foo", "foo"
|
||||||
|
];
|
||||||
|
|
||||||
|
var actual_targets = [], actual_types = [];
|
||||||
|
var test_event = this.step_func(function(evt) {
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_types.push(evt.type);
|
||||||
|
|
||||||
|
if (table == evt.currentTarget && event_type == evt.type) {
|
||||||
|
var e = document.createEvent("Event");
|
||||||
|
e.initEvent("bar", true, true);
|
||||||
|
target.dispatchEvent(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; ++i) {
|
||||||
|
targets[i].addEventListener(event_type, test_event, true);
|
||||||
|
targets[i].addEventListener("bar", test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, false, true);
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "actual_targets");
|
||||||
|
assert_array_equals(actual_types, expected_types, "actual_types");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,164 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Only one activation behavior is executed during dispatch</title>
|
||||||
|
<link rel="author" title="Vincent Hilla" href="mailto:vhilla@mozilla.com">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget-activation-behavior">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
|
||||||
|
<div id=test_container></div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Three classes:
|
||||||
|
click
|
||||||
|
Element to be clicked to cause activation behavior
|
||||||
|
activates
|
||||||
|
Element that registers the activation behavior
|
||||||
|
container
|
||||||
|
Element in which other elements with activation behavior are placed.
|
||||||
|
We test that those won't be activated too.
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<!--input, change event bubble, so have to check if checked is true-->
|
||||||
|
<input class="click activates container" type="checkbox" oninput="this.checked ? activated(this) : null">
|
||||||
|
<input class="click activates container" type="radio" oninput="this.checked ? activated(this) : null">
|
||||||
|
<form onsubmit="activated(this); return false" class="activates">
|
||||||
|
<input class="click container" type="submit">
|
||||||
|
</form>
|
||||||
|
<form onsubmit="activated(this); return false" class="activates">
|
||||||
|
<input class="click container" type="image">
|
||||||
|
</form>
|
||||||
|
<form onreset="activated(this)" class="activates">
|
||||||
|
<input class="click container" type="reset">
|
||||||
|
</form>
|
||||||
|
<form onsubmit="activated(this); return false" class="activates">
|
||||||
|
<button class="click container" type="submit"></button>
|
||||||
|
</form>
|
||||||
|
<form onreset="activated(this)" class="activates">
|
||||||
|
<button class="click container" type="reset"></button>
|
||||||
|
</form>
|
||||||
|
<a href="#link" class="click container activates"></a>
|
||||||
|
<area href="#link" class="click container activates">
|
||||||
|
<details ontoggle="activated(this)" class="activates">
|
||||||
|
<summary class="click container"></summary>
|
||||||
|
</details>
|
||||||
|
<label>
|
||||||
|
<input type=checkbox onclick="this.checked ? activated(this) : null" class="activates">
|
||||||
|
<span class="click container">label</span>
|
||||||
|
</label>
|
||||||
|
<!--activation behavior of label for event targeted at interactive content descendant is to do nothing-->
|
||||||
|
<label class="container">
|
||||||
|
<button class="click" type="button"></button>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let activations = [];
|
||||||
|
function activated(e) {
|
||||||
|
activations.push(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getActivations(testidx) {
|
||||||
|
return activations.filter(a =>
|
||||||
|
(a.endsWith && a.endsWith("test"+testidx+"_link"))
|
||||||
|
|| (a.classList && a.classList.contains("test"+testidx))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for a and area elements
|
||||||
|
window.onhashchange = function(e) {
|
||||||
|
if (e.newURL.endsWith("link")) {
|
||||||
|
activated(e.newURL);
|
||||||
|
}
|
||||||
|
window.location.hash = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
function getElementsByClassNameInclusive(e, clsname) {
|
||||||
|
let ls = Array.from(e.getElementsByClassName(clsname));
|
||||||
|
if (e.classList.contains(clsname)) ls.push(e);
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClickTarget(e) {
|
||||||
|
return getElementsByClassNameInclusive(e, "click")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContainer(e) {
|
||||||
|
return getElementsByClassNameInclusive(e, "container")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getExpectedActivations(e) {
|
||||||
|
let ls = getElementsByClassNameInclusive(e, "activates");
|
||||||
|
|
||||||
|
// special case, for a and area the window registers the activation
|
||||||
|
// have to use string, as testrunner cannot stringify the window object
|
||||||
|
ls = ls.map(e => e.tagName === "A" || e.tagName === "AREA" ? e.href : e);
|
||||||
|
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toString(e) {
|
||||||
|
const children = Array.from(e.children);
|
||||||
|
const childstr = (children.map(toString)).join("");
|
||||||
|
const tag = e.tagName;
|
||||||
|
const typestr = e.type ? " type="+e.type : "";
|
||||||
|
return `<${tag}${typestr}>${childstr}</${tag}>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate O(n^2) test combinations
|
||||||
|
const template = document.querySelector("template");
|
||||||
|
const elements = Array.from(template.content.children);
|
||||||
|
const tests = []
|
||||||
|
for (const target of elements) {
|
||||||
|
for (const parent of elements) {
|
||||||
|
if (target === parent) continue;
|
||||||
|
tests.push([target.cloneNode(true), parent.cloneNode(true)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const test_container = document.getElementById("test_container");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that if two elements in an event target chain have activation behavior,
|
||||||
|
* only one of them will be activated.
|
||||||
|
*
|
||||||
|
* Each child of <template> represents one case of activation behavior.
|
||||||
|
* The behavior should be triggered by clicking the element of class click
|
||||||
|
* and will manifest as a call to activated().
|
||||||
|
*
|
||||||
|
* For each [target, parent] in tests, we make target a descendant of parent
|
||||||
|
* and test that only target gets activated when dispatching a click.
|
||||||
|
*/
|
||||||
|
for (let i = 0; i < tests.length; i++) {
|
||||||
|
let [target, parent] = tests[i];
|
||||||
|
async_test(function(t) {
|
||||||
|
let test = document.createElement("div");
|
||||||
|
test_container.appendChild(test);
|
||||||
|
test.appendChild(parent);
|
||||||
|
getContainer(parent).appendChild(target);
|
||||||
|
|
||||||
|
// for later filtering out the activations belonging to this test
|
||||||
|
for (let e of test.getElementsByClassName("activates")) {
|
||||||
|
e.classList.add("test"+i);
|
||||||
|
}
|
||||||
|
for (let e of test.querySelectorAll("a, area")) {
|
||||||
|
e.href = "#test"+i+"_link";
|
||||||
|
}
|
||||||
|
|
||||||
|
getClickTarget(target).click();
|
||||||
|
|
||||||
|
// Need to spin event loop twice, as some clicks might dispatch another task
|
||||||
|
t.step_timeout(() => {
|
||||||
|
t.step_timeout(t.step_func_done(() => {
|
||||||
|
assert_array_equals(getActivations(i), getExpectedActivations(target));
|
||||||
|
}), 0);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
t.add_cleanup(function() {
|
||||||
|
test_container.removeChild(test);
|
||||||
|
});
|
||||||
|
}, `When clicking child ${toString(target)} of parent ${toString(parent)}, only child should be activated.`);
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,73 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title> Determined event propagation path - target moved </title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
|
||||||
|
var phases = [
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
];
|
||||||
|
|
||||||
|
var actual_targets = [], actual_phases = [];
|
||||||
|
var test_event = this.step_func(function(evt) {
|
||||||
|
if (parent === target.parentNode) {
|
||||||
|
var table_row = document.getElementById("table-row");
|
||||||
|
table_row.appendChild(parent.removeChild(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].addEventListener(event_type, test_event, true);
|
||||||
|
targets[i].addEventListener(event_type, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "targets");
|
||||||
|
assert_array_equals(actual_phases, phases, "phases");
|
||||||
|
}, "Event propagation path when an element in it is moved within the DOM");
|
||||||
|
</script>
|
|
@ -0,0 +1,72 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset=utf-8>
|
||||||
|
<title>Determined event propagation path - target removed</title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id=log></div>
|
||||||
|
<table id="table" border="1" style="display: none">
|
||||||
|
<tbody id="table-body">
|
||||||
|
<tr id="table-row">
|
||||||
|
<td id="table-cell">Shady Grove</td>
|
||||||
|
<td>Aeolian</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="parent">
|
||||||
|
<td id="target">Over the river, Charlie</td>
|
||||||
|
<td>Dorian</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var event_type = "foo";
|
||||||
|
var target = document.getElementById("target");
|
||||||
|
var parent = document.getElementById("parent");
|
||||||
|
var tbody = document.getElementById("table-body");
|
||||||
|
var table = document.getElementById("table");
|
||||||
|
var body = document.body;
|
||||||
|
var html = document.documentElement;
|
||||||
|
var targets = [window, document, html, body, table, tbody, parent, target];
|
||||||
|
var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
|
||||||
|
var phases = [
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.CAPTURING_PHASE,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.AT_TARGET,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
Event.BUBBLING_PHASE,
|
||||||
|
];
|
||||||
|
|
||||||
|
var actual_targets = [], actual_phases = [];
|
||||||
|
var test_event = this.step_func(function(evt) {
|
||||||
|
if (parent === target.parentNode) {
|
||||||
|
parent.removeChild(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_targets.push(evt.currentTarget);
|
||||||
|
actual_phases.push(evt.eventPhase);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < targets.length; i++) {
|
||||||
|
targets[i].addEventListener(event_type, test_event, true);
|
||||||
|
targets[i].addEventListener(event_type, test_event, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var evt = document.createEvent("Event");
|
||||||
|
evt.initEvent(event_type, true, true);
|
||||||
|
target.dispatchEvent(evt);
|
||||||
|
|
||||||
|
assert_array_equals(actual_targets, expected_targets, "targets");
|
||||||
|
assert_array_equals(actual_phases, phases, "phases");
|
||||||
|
}, "Event propagation path when an element in it is removed from the DOM");
|
||||||
|
</script>
|
|
@ -0,0 +1,69 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
function createIframe(t, srcdoc = '') {
|
||||||
|
let iframe = document.createElement('iframe');
|
||||||
|
iframe.srcdoc = srcdoc;
|
||||||
|
t.add_cleanup(() => iframe.remove());
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
iframe.addEventListener('load', () => resolve(iframe.contentWindow));
|
||||||
|
document.body.appendChild(iframe);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a promise which will resolve with the next error event fired at any
|
||||||
|
// of `windows`, after the invocation of this function. Once one does, this
|
||||||
|
// function removes its listeners and produces that error event so that it can
|
||||||
|
// be examined (most notably for which global proxy it was targeted at).
|
||||||
|
async function nextErrorEvent(windows) {
|
||||||
|
let listener;
|
||||||
|
let p = new Promise((resolve, reject) => {
|
||||||
|
listener = (event) => { resolve(event); event.preventDefault(); };
|
||||||
|
});
|
||||||
|
for (let w of windows) {
|
||||||
|
w.addEventListener('error', listener);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return await p;
|
||||||
|
} finally {
|
||||||
|
for (let w of windows) {
|
||||||
|
w.removeEventListener('error', listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
let w = await createIframe(t, `<script>function listener() { throw new Error(); }<`+`/script>`);
|
||||||
|
let w2 = await createIframe(t);
|
||||||
|
|
||||||
|
let target = new w2.EventTarget();
|
||||||
|
target.addEventListener('party', w.listener);
|
||||||
|
let nextErrorPromise = nextErrorEvent([self, w, w2]);
|
||||||
|
target.dispatchEvent(new Event('party'));
|
||||||
|
let errorEvent = await nextErrorPromise;
|
||||||
|
if (errorEvent.error) {
|
||||||
|
assert_true(errorEvent.error instanceof w.Error, 'error should be an instance created inside the listener function');
|
||||||
|
}
|
||||||
|
assert_equals(errorEvent.target, w, `error event should target listener's global but instead targets ${event.currentTarget === w2 ? 'target\'s global' : 'test harness global'}`);
|
||||||
|
}, 'exception thrown in event listener function should result in error event on listener\'s global');
|
||||||
|
|
||||||
|
promise_test(async t => {
|
||||||
|
let w = await createIframe(t, `<script>listener = {};<`+`/script>`);
|
||||||
|
let w2 = await createIframe(t, `<script>handleEvent = () => { throw new Error; };<`+`/script>`);
|
||||||
|
let w3 = await createIframe(t);
|
||||||
|
w.listener.handleEvent = w2.handleEvent;
|
||||||
|
|
||||||
|
let target = new w3.EventTarget();
|
||||||
|
target.addEventListener('party', w.listener);
|
||||||
|
let nextErrorPromise = nextErrorEvent([self, w, w2, w3]);
|
||||||
|
target.dispatchEvent(new Event('party'));
|
||||||
|
let errorEvent = await nextErrorPromise;
|
||||||
|
if (errorEvent.error) {
|
||||||
|
assert_true(errorEvent.error instanceof w2.Error, 'error should be an instance created inside the listener function');
|
||||||
|
}
|
||||||
|
assert_equals(errorEvent.target, w, `error event should target listener's global but instead targets ${event.currentTarget === w2 ? 'target\'s global' : event.currentTarget === w3 ? 'function\'s global' : 'test harness global'}`);
|
||||||
|
}, 'exception thrown in event listener interface object should result in error event on listener\'s global');
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,51 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Throwing in event listeners</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
setup({allow_uncaught_exception:true})
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var errorEvents = 0;
|
||||||
|
window.onerror = this.step_func(function(e) {
|
||||||
|
assert_equals(typeof e, 'string');
|
||||||
|
++errorEvents;
|
||||||
|
});
|
||||||
|
|
||||||
|
var element = document.createElement('div');
|
||||||
|
|
||||||
|
element.addEventListener('click', function() {
|
||||||
|
throw new Error('Error from only listener');
|
||||||
|
});
|
||||||
|
|
||||||
|
element.dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
|
assert_equals(errorEvents, 1);
|
||||||
|
}, "Throwing in event listener with a single listeners");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var errorEvents = 0;
|
||||||
|
window.onerror = this.step_func(function(e) {
|
||||||
|
assert_equals(typeof e, 'string');
|
||||||
|
++errorEvents;
|
||||||
|
});
|
||||||
|
|
||||||
|
var element = document.createElement('div');
|
||||||
|
|
||||||
|
var secondCalled = false;
|
||||||
|
|
||||||
|
element.addEventListener('click', function() {
|
||||||
|
throw new Error('Error from first listener');
|
||||||
|
});
|
||||||
|
element.addEventListener('click', this.step_func(function() {
|
||||||
|
secondCalled = true;
|
||||||
|
}), false);
|
||||||
|
|
||||||
|
element.dispatchEvent(new Event('click'));
|
||||||
|
|
||||||
|
assert_equals(errorEvents, 1);
|
||||||
|
assert_true(secondCalled);
|
||||||
|
}, "Throwing in event listener with multiple listeners");
|
||||||
|
</script>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Re-initializing events while dispatching them</title>
|
||||||
|
<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var events = {
|
||||||
|
'KeyboardEvent': {
|
||||||
|
'constructor': function() { return new KeyboardEvent("type", {key: "A"}); },
|
||||||
|
'init': function(ev) { ev.initKeyboardEvent("type2", true, true, null, "a", 1, "", true, "") },
|
||||||
|
'check': function(ev) {
|
||||||
|
assert_equals(ev.key, "A", "initKeyboardEvent key setter should short-circuit");
|
||||||
|
assert_false(ev.repeat, "initKeyboardEvent repeat setter should short-circuit");
|
||||||
|
assert_equals(ev.location, 0, "initKeyboardEvent location setter should short-circuit");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'MouseEvent': {
|
||||||
|
'constructor': function() { return new MouseEvent("type"); },
|
||||||
|
'init': function(ev) { ev.initMouseEvent("type2", true, true, null, 0, 1, 1, 1, 1, true, true, true, true, 1, null) },
|
||||||
|
'check': function(ev) {
|
||||||
|
assert_equals(ev.screenX, 0, "initMouseEvent screenX setter should short-circuit");
|
||||||
|
assert_equals(ev.screenY, 0, "initMouseEvent screenY setter should short-circuit");
|
||||||
|
assert_equals(ev.clientX, 0, "initMouseEvent clientX setter should short-circuit");
|
||||||
|
assert_equals(ev.clientY, 0, "initMouseEvent clientY setter should short-circuit");
|
||||||
|
assert_false(ev.ctrlKey, "initMouseEvent ctrlKey setter should short-circuit");
|
||||||
|
assert_false(ev.altKey, "initMouseEvent altKey setter should short-circuit");
|
||||||
|
assert_false(ev.shiftKey, "initMouseEvent shiftKey setter should short-circuit");
|
||||||
|
assert_false(ev.metaKey, "initMouseEvent metaKey setter should short-circuit");
|
||||||
|
assert_equals(ev.button, 0, "initMouseEvent button setter should short-circuit");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'CustomEvent': {
|
||||||
|
'constructor': function() { return new CustomEvent("type") },
|
||||||
|
'init': function(ev) { ev.initCustomEvent("type2", true, true, 1) },
|
||||||
|
'check': function(ev) {
|
||||||
|
assert_equals(ev.detail, null, "initCustomEvent detail setter should short-circuit");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'UIEvent': {
|
||||||
|
'constructor': function() { return new UIEvent("type") },
|
||||||
|
'init': function(ev) { ev.initUIEvent("type2", true, true, window, 1) },
|
||||||
|
'check': function(ev) {
|
||||||
|
assert_equals(ev.view, null, "initUIEvent view setter should short-circuit");
|
||||||
|
assert_equals(ev.detail, 0, "initUIEvent detail setter should short-circuit");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Event': {
|
||||||
|
'constructor': function() { return new Event("type") },
|
||||||
|
'init': function(ev) { ev.initEvent("type2", true, true) },
|
||||||
|
'check': function(ev) {
|
||||||
|
assert_equals(ev.bubbles, false, "initEvent bubbles setter should short-circuit");
|
||||||
|
assert_equals(ev.cancelable, false, "initEvent cancelable setter should short-circuit");
|
||||||
|
assert_equals(ev.type, "type", "initEvent type setter should short-circuit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var names = Object.keys(events);
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
var t = async_test("Calling init" + names[i] + " while dispatching.");
|
||||||
|
t.step(function() {
|
||||||
|
var e = events[names[i]].constructor();
|
||||||
|
|
||||||
|
var target = document.createElement("div")
|
||||||
|
target.addEventListener("type", t.step_func(function() {
|
||||||
|
events[names[i]].init(e);
|
||||||
|
|
||||||
|
var o = e;
|
||||||
|
while ((o = Object.getPrototypeOf(o))) {
|
||||||
|
if (!(o.constructor.name in events)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
events[o.constructor.name].check(e);
|
||||||
|
}
|
||||||
|
}), false);
|
||||||
|
|
||||||
|
assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
|
||||||
|
});
|
||||||
|
t.done();
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,136 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Event.initEvent</title>
|
||||||
|
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
var booleans = [true, false];
|
||||||
|
booleans.forEach(function(bubbles) {
|
||||||
|
booleans.forEach(function(cancelable) {
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type", bubbles, cancelable)
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
// Stop (immediate) propagation flag is tested later
|
||||||
|
assert_equals(e.defaultPrevented, false, "defaultPrevented")
|
||||||
|
assert_equals(e.returnValue, true, "returnValue")
|
||||||
|
// Step 3.
|
||||||
|
assert_equals(e.isTrusted, false, "isTrusted")
|
||||||
|
// Step 4.
|
||||||
|
assert_equals(e.target, null, "target")
|
||||||
|
assert_equals(e.srcElement, null, "srcElement")
|
||||||
|
// Step 5.
|
||||||
|
assert_equals(e.type, "type", "type")
|
||||||
|
// Step 6.
|
||||||
|
assert_equals(e.bubbles, bubbles, "bubbles")
|
||||||
|
// Step 7.
|
||||||
|
assert_equals(e.cancelable, cancelable, "cancelable")
|
||||||
|
}, "Properties of initEvent(type, " + bubbles + ", " + cancelable + ")")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type 1", true, false)
|
||||||
|
assert_equals(e.type, "type 1", "type (first init)")
|
||||||
|
assert_equals(e.bubbles, true, "bubbles (first init)")
|
||||||
|
assert_equals(e.cancelable, false, "cancelable (first init)")
|
||||||
|
|
||||||
|
e.initEvent("type 2", false, true)
|
||||||
|
assert_equals(e.type, "type 2", "type (second init)")
|
||||||
|
assert_equals(e.bubbles, false, "bubbles (second init)")
|
||||||
|
assert_equals(e.cancelable, true, "cancelable (second init)")
|
||||||
|
}, "Calling initEvent multiple times (getting type).")
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=998809
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type 1", true, false)
|
||||||
|
assert_equals(e.bubbles, true, "bubbles (first init)")
|
||||||
|
assert_equals(e.cancelable, false, "cancelable (first init)")
|
||||||
|
|
||||||
|
e.initEvent("type 2", false, true)
|
||||||
|
assert_equals(e.type, "type 2", "type (second init)")
|
||||||
|
assert_equals(e.bubbles, false, "bubbles (second init)")
|
||||||
|
assert_equals(e.cancelable, true, "cancelable (second init)")
|
||||||
|
}, "Calling initEvent multiple times (not getting type).")
|
||||||
|
|
||||||
|
// Step 2.
|
||||||
|
async_test(function() {
|
||||||
|
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=17715
|
||||||
|
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type", false, false)
|
||||||
|
assert_equals(e.type, "type", "type (first init)")
|
||||||
|
assert_equals(e.bubbles, false, "bubbles (first init)")
|
||||||
|
assert_equals(e.cancelable, false, "cancelable (first init)")
|
||||||
|
|
||||||
|
var target = document.createElement("div")
|
||||||
|
target.addEventListener("type", this.step_func(function() {
|
||||||
|
e.initEvent("fail", true, true)
|
||||||
|
assert_equals(e.type, "type", "type (second init)")
|
||||||
|
assert_equals(e.bubbles, false, "bubbles (second init)")
|
||||||
|
assert_equals(e.cancelable, false, "cancelable (second init)")
|
||||||
|
}), false)
|
||||||
|
|
||||||
|
assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
|
||||||
|
|
||||||
|
this.done()
|
||||||
|
}, "Calling initEvent must not have an effect during dispatching.")
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.stopPropagation()
|
||||||
|
e.initEvent("type", false, false)
|
||||||
|
var target = document.createElement("div")
|
||||||
|
var called = false
|
||||||
|
target.addEventListener("type", function() { called = true }, false)
|
||||||
|
assert_false(e.cancelBubble, "cancelBubble must be false")
|
||||||
|
assert_true(target.dispatchEvent(e), "dispatchEvent must return true")
|
||||||
|
assert_true(called, "Listener must be called")
|
||||||
|
}, "Calling initEvent must unset the stop propagation flag.")
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.stopImmediatePropagation()
|
||||||
|
e.initEvent("type", false, false)
|
||||||
|
var target = document.createElement("div")
|
||||||
|
var called = false
|
||||||
|
target.addEventListener("type", function() { called = true }, false)
|
||||||
|
assert_true(target.dispatchEvent(e), "dispatchEvent must return true")
|
||||||
|
assert_true(called, "Listener must be called")
|
||||||
|
}, "Calling initEvent must unset the stop immediate propagation flag.")
|
||||||
|
|
||||||
|
async_test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type", false, false)
|
||||||
|
|
||||||
|
var target = document.createElement("div")
|
||||||
|
target.addEventListener("type", this.step_func(function() {
|
||||||
|
e.initEvent("type2", true, true);
|
||||||
|
assert_equals(e.type, "type", "initEvent type setter should short-circuit");
|
||||||
|
assert_false(e.bubbles, "initEvent bubbles setter should short-circuit");
|
||||||
|
assert_false(e.cancelable, "initEvent cancelable setter should short-circuit");
|
||||||
|
}), false)
|
||||||
|
assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
|
||||||
|
|
||||||
|
this.done()
|
||||||
|
}, "Calling initEvent during propagation.")
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
assert_throws_js(TypeError, function() {
|
||||||
|
e.initEvent()
|
||||||
|
})
|
||||||
|
}, "First parameter to initEvent should be mandatory.")
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("type")
|
||||||
|
assert_equals(e.type, "type", "type")
|
||||||
|
assert_false(e.bubbles, "bubbles")
|
||||||
|
assert_false(e.cancelable, "cancelable")
|
||||||
|
}, "Tests initEvent's default parameter values.")
|
||||||
|
</script>
|
|
@ -0,0 +1,11 @@
|
||||||
|
test(function() {
|
||||||
|
var desc1 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
|
||||||
|
assert_not_equals(desc1, undefined);
|
||||||
|
assert_equals(typeof desc1.get, "function");
|
||||||
|
|
||||||
|
var desc2 = Object.getOwnPropertyDescriptor(new Event("x"), "isTrusted");
|
||||||
|
assert_not_equals(desc2, undefined);
|
||||||
|
assert_equals(typeof desc2.get, "function");
|
||||||
|
|
||||||
|
assert_equals(desc1.get, desc2.get);
|
||||||
|
});
|
|
@ -0,0 +1,48 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Event propagation tests</title>
|
||||||
|
<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
|
||||||
|
<div id=log></div>
|
||||||
|
<script src=../../resources/testharness.js></script>
|
||||||
|
<script src=../../resources/testharnessreport.js></script>
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function testPropagationFlag(ev, expected, desc) {
|
||||||
|
test(function() {
|
||||||
|
var called = false;
|
||||||
|
var callback = function() { called = true };
|
||||||
|
this.add_cleanup(function() {
|
||||||
|
document.head.removeEventListener("foo", callback)
|
||||||
|
});
|
||||||
|
document.head.addEventListener("foo", callback);
|
||||||
|
document.head.dispatchEvent(ev);
|
||||||
|
assert_equals(called, expected, "Propagation flag");
|
||||||
|
// dispatchEvent resets the propagation flags so it will happily dispatch
|
||||||
|
// the event the second time around.
|
||||||
|
document.head.dispatchEvent(ev);
|
||||||
|
assert_equals(called, true, "Propagation flag after first dispatch");
|
||||||
|
}, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ev = document.createEvent("Event");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
testPropagationFlag(ev, true, "Newly-created Event");
|
||||||
|
ev.stopPropagation();
|
||||||
|
testPropagationFlag(ev, false, "After stopPropagation()");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
testPropagationFlag(ev, true, "Reinitialized after stopPropagation()");
|
||||||
|
|
||||||
|
var ev = document.createEvent("Event");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
ev.stopImmediatePropagation();
|
||||||
|
testPropagationFlag(ev, false, "After stopImmediatePropagation()");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
testPropagationFlag(ev, true, "Reinitialized after stopImmediatePropagation()");
|
||||||
|
|
||||||
|
var ev = document.createEvent("Event");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
ev.cancelBubble = true;
|
||||||
|
testPropagationFlag(ev, false, "After cancelBubble=true");
|
||||||
|
ev.initEvent("foo", true, false);
|
||||||
|
testPropagationFlag(ev, true, "Reinitialized after cancelBubble=true");
|
||||||
|
</script>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Event.returnValue</title>
|
||||||
|
<link rel="author" title="Chris Rebert" href="http://chrisrebert.com">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-returnvalue">
|
||||||
|
<meta name="flags" content="dom">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo");
|
||||||
|
assert_true(ev.returnValue, "returnValue");
|
||||||
|
}, "When an event is created, returnValue should be initialized to true.");
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo", {"cancelable": false});
|
||||||
|
assert_false(ev.cancelable, "cancelable (before)");
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_false(ev.cancelable, "cancelable (after)");
|
||||||
|
assert_true(ev.returnValue, "returnValue");
|
||||||
|
}, "preventDefault() should not change returnValue if cancelable is false.");
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo", {"cancelable": false});
|
||||||
|
assert_false(ev.cancelable, "cancelable (before)");
|
||||||
|
ev.returnValue = false;
|
||||||
|
assert_false(ev.cancelable, "cancelable (after)");
|
||||||
|
assert_true(ev.returnValue, "returnValue");
|
||||||
|
}, "returnValue=false should have no effect if cancelable is false.");
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo", {"cancelable": true});
|
||||||
|
assert_true(ev.cancelable, "cancelable (before)");
|
||||||
|
ev.preventDefault();
|
||||||
|
assert_true(ev.cancelable, "cancelable (after)");
|
||||||
|
assert_false(ev.returnValue, "returnValue");
|
||||||
|
}, "preventDefault() should change returnValue if cancelable is true.");
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo", {"cancelable": true});
|
||||||
|
assert_true(ev.cancelable, "cancelable (before)");
|
||||||
|
ev.returnValue = false;
|
||||||
|
assert_true(ev.cancelable, "cancelable (after)");
|
||||||
|
assert_false(ev.returnValue, "returnValue");
|
||||||
|
}, "returnValue should change returnValue if cancelable is true.");
|
||||||
|
test(function() {
|
||||||
|
var ev = document.createEvent("Event");
|
||||||
|
ev.returnValue = false;
|
||||||
|
ev.initEvent("foo", true, true);
|
||||||
|
assert_true(ev.bubbles, "bubbles");
|
||||||
|
assert_true(ev.cancelable, "cancelable");
|
||||||
|
assert_true(ev.returnValue, "returnValue");
|
||||||
|
}, "initEvent should unset returnValue.");
|
||||||
|
test(function() {
|
||||||
|
var ev = new Event("foo", {"cancelable": true});
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.returnValue = true;// no-op
|
||||||
|
assert_true(ev.defaultPrevented);
|
||||||
|
assert_false(ev.returnValue);
|
||||||
|
}, "returnValue=true should have no effect once the canceled flag was set.");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Event's stopImmediatePropagation</title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation">
|
||||||
|
<link rel="author" href="mailto:d@domenic.me" title="Domenic Denicola">
|
||||||
|
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<div id="target"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
setup({ single_test: true });
|
||||||
|
|
||||||
|
const target = document.querySelector("#target");
|
||||||
|
|
||||||
|
let timesCalled = 0;
|
||||||
|
target.addEventListener("test", e => {
|
||||||
|
++timesCalled;
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
assert_equals(e.cancelBubble, true, "The stop propagation flag must have been set");
|
||||||
|
});
|
||||||
|
target.addEventListener("test", () => {
|
||||||
|
++timesCalled;
|
||||||
|
});
|
||||||
|
|
||||||
|
const e = new Event("test");
|
||||||
|
target.dispatchEvent(e);
|
||||||
|
assert_equals(timesCalled, 1, "The second listener must not have been called");
|
||||||
|
|
||||||
|
done();
|
||||||
|
</script>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="author" title="Joey Arhar" href="mailto:jarhar@chromium.org">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
test(t => {
|
||||||
|
const element = document.createElement('div');
|
||||||
|
|
||||||
|
element.addEventListener('click', () => {
|
||||||
|
event.stopPropagation();
|
||||||
|
}, { capture: true });
|
||||||
|
|
||||||
|
element.addEventListener('click',
|
||||||
|
t.unreached_func('stopPropagation in the capture handler should have canceled this bubble handler.'));
|
||||||
|
|
||||||
|
element.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,179 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Event constructors</title>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
function assert_props(iface, event, defaults) {
|
||||||
|
assert_true(event instanceof self[iface]);
|
||||||
|
expected[iface].properties.forEach(function(p) {
|
||||||
|
var property = p[0], value = p[defaults ? 1 : 2];
|
||||||
|
assert_true(property in event,
|
||||||
|
"Event " + format_value(event) + " should have a " +
|
||||||
|
property + " property");
|
||||||
|
assert_equals(event[property], value,
|
||||||
|
"The value of the " + property + " property should be " +
|
||||||
|
format_value(value));
|
||||||
|
});
|
||||||
|
if ("parent" in expected[iface]) {
|
||||||
|
assert_props(expected[iface].parent, event, defaults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Class declarations don't go on the global by default, so put it there ourselves:
|
||||||
|
|
||||||
|
self.SubclassedEvent = class SubclassedEvent extends Event {
|
||||||
|
constructor(name, props) {
|
||||||
|
super(name, props);
|
||||||
|
if (props && typeof(props) == "object" && "customProp" in props) {
|
||||||
|
this.customProp = props.customProp;
|
||||||
|
} else {
|
||||||
|
this.customProp = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get fixedProp() {
|
||||||
|
return 17;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var EventModifierInit = [
|
||||||
|
["ctrlKey", false, true],
|
||||||
|
["shiftKey", false, true],
|
||||||
|
["altKey", false, true],
|
||||||
|
["metaKey", false, true],
|
||||||
|
];
|
||||||
|
var expected = {
|
||||||
|
"Event": {
|
||||||
|
"properties": [
|
||||||
|
["bubbles", false, true],
|
||||||
|
["cancelable", false, true],
|
||||||
|
["isTrusted", false, false],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"UIEvent": {
|
||||||
|
"parent": "Event",
|
||||||
|
"properties": [
|
||||||
|
["view", null, window],
|
||||||
|
["detail", 0, 7],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"FocusEvent": {
|
||||||
|
"parent": "UIEvent",
|
||||||
|
"properties": [
|
||||||
|
["relatedTarget", null, document],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"MouseEvent": {
|
||||||
|
"parent": "UIEvent",
|
||||||
|
"properties": EventModifierInit.concat([
|
||||||
|
["screenX", 0, 40],
|
||||||
|
["screenY", 0, 40],
|
||||||
|
["clientX", 0, 40],
|
||||||
|
["clientY", 0, 40],
|
||||||
|
["button", 0, 40],
|
||||||
|
["buttons", 0, 40],
|
||||||
|
["relatedTarget", null, document],
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
|
||||||
|
"WheelEvent": {
|
||||||
|
"parent": "MouseEvent",
|
||||||
|
"properties": [
|
||||||
|
["deltaX", 0.0, 3.1],
|
||||||
|
["deltaY", 0.0, 3.1],
|
||||||
|
["deltaZ", 0.0, 3.1],
|
||||||
|
["deltaMode", 0, 40],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"KeyboardEvent": {
|
||||||
|
"parent": "UIEvent",
|
||||||
|
"properties": EventModifierInit.concat([
|
||||||
|
["key", "", "string"],
|
||||||
|
["code", "", "string"],
|
||||||
|
["location", 0, 7],
|
||||||
|
["repeat", false, true],
|
||||||
|
["isComposing", false, true],
|
||||||
|
["charCode", 0, 7],
|
||||||
|
["keyCode", 0, 7],
|
||||||
|
["which", 0, 7],
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
|
||||||
|
"CompositionEvent": {
|
||||||
|
"parent": "UIEvent",
|
||||||
|
"properties": [
|
||||||
|
["data", "", "string"],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"SubclassedEvent": {
|
||||||
|
"parent": "Event",
|
||||||
|
"properties": [
|
||||||
|
["customProp", 5, 8],
|
||||||
|
["fixedProp", 17, 17],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(expected).forEach(function(iface) {
|
||||||
|
test(function() {
|
||||||
|
var event = new self[iface]("type");
|
||||||
|
assert_props(iface, event, true);
|
||||||
|
}, iface + " constructor (no argument)");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var event = new self[iface]("type", undefined);
|
||||||
|
assert_props(iface, event, true);
|
||||||
|
}, iface + " constructor (undefined argument)");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var event = new self[iface]("type", null);
|
||||||
|
assert_props(iface, event, true);
|
||||||
|
}, iface + " constructor (null argument)");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var event = new self[iface]("type", {});
|
||||||
|
assert_props(iface, event, true);
|
||||||
|
}, iface + " constructor (empty argument)");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var dictionary = {};
|
||||||
|
expected[iface].properties.forEach(function(p) {
|
||||||
|
var property = p[0], value = p[1];
|
||||||
|
dictionary[property] = value;
|
||||||
|
});
|
||||||
|
var event = new self[iface]("type", dictionary);
|
||||||
|
assert_props(iface, event, true);
|
||||||
|
}, iface + " constructor (argument with default values)");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
function fill_in(iface, dictionary) {
|
||||||
|
if ("parent" in expected[iface]) {
|
||||||
|
fill_in(expected[iface].parent, dictionary)
|
||||||
|
}
|
||||||
|
expected[iface].properties.forEach(function(p) {
|
||||||
|
var property = p[0], value = p[2];
|
||||||
|
dictionary[property] = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var dictionary = {};
|
||||||
|
fill_in(iface, dictionary);
|
||||||
|
|
||||||
|
var event = new self[iface]("type", dictionary);
|
||||||
|
assert_props(iface, event, false);
|
||||||
|
}, iface + " constructor (argument with non-default values)");
|
||||||
|
});
|
||||||
|
|
||||||
|
test(function () {
|
||||||
|
assert_throws_js(TypeError, function() {
|
||||||
|
new UIEvent("x", { view: 7 })
|
||||||
|
});
|
||||||
|
}, "UIEvent constructor (view argument with wrong type)")
|
||||||
|
</script>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>event.timeStamp is initialized using event's relevant global object</title>
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#ref-for-dom-event-timestamp%E2%91%A1">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
const t = async_test();
|
||||||
|
t.step_timeout(() => {
|
||||||
|
const iframeDelayed = document.createElement("iframe");
|
||||||
|
iframeDelayed.onload = t.step_func_done(() => {
|
||||||
|
// Use eval() to eliminate false-positive test result for WebKit builds before r280256,
|
||||||
|
// which invoked WebIDL accessors in context of lexical (caller) global object.
|
||||||
|
const timeStampExpected = iframeDelayed.contentWindow.eval(`new Event("foo").timeStamp`);
|
||||||
|
const eventDelayed = new iframeDelayed.contentWindow.Event("foo");
|
||||||
|
|
||||||
|
const {get} = Object.getOwnPropertyDescriptor(Event.prototype, "timeStamp");
|
||||||
|
assert_approx_equals(get.call(eventDelayed), timeStampExpected, 5, "via Object.getOwnPropertyDescriptor");
|
||||||
|
|
||||||
|
Object.setPrototypeOf(eventDelayed, Event.prototype);
|
||||||
|
assert_approx_equals(eventDelayed.timeStamp, timeStampExpected, 5, "via Object.setPrototypeOf");
|
||||||
|
});
|
||||||
|
document.body.append(iframeDelayed);
|
||||||
|
}, 1000);
|
||||||
|
</script>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
'use strict';
|
||||||
|
for (let eventType of ["MouseEvent", "KeyboardEvent", "WheelEvent", "FocusEvent"]) {
|
||||||
|
test(function() {
|
||||||
|
let before = performance.now();
|
||||||
|
let e = new window[eventType]('test');
|
||||||
|
let after = performance.now();
|
||||||
|
assert_greater_than_equal(e.timeStamp, before, "Event timestamp should be greater than performance.now() timestamp taken before its creation");
|
||||||
|
assert_less_than_equal(e.timeStamp, after, "Event timestamp should be less than performance.now() timestamp taken after its creation");
|
||||||
|
}, `Constructed ${eventType} timestamp should be high resolution and have the same time origin as performance.now()`);
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
'use strict';
|
||||||
|
for (let eventType of ["GamepadEvent"]) {
|
||||||
|
test(function() {
|
||||||
|
let before = performance.now();
|
||||||
|
let e = new window[eventType]('test');
|
||||||
|
let after = performance.now();
|
||||||
|
assert_greater_than_equal(e.timeStamp, before, "Event timestamp should be greater than performance.now() timestamp taken before its creation");
|
||||||
|
assert_less_than_equal(e.timeStamp, after, "Event timestamp should be less than performance.now() timestamp taken after its creation");
|
||||||
|
}, `Constructed ${eventType} timestamp should be high resolution and have the same time origin as performance.now()`);
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,49 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Computes greatest common divisor of a and b using Euclid's algorithm
|
||||||
|
function computeGCD(a, b) {
|
||||||
|
if (!Number.isInteger(a) || !Number.isInteger(b)) {
|
||||||
|
throw new Error('Parameters must be integer numbers');
|
||||||
|
}
|
||||||
|
|
||||||
|
var r;
|
||||||
|
while (b != 0) {
|
||||||
|
r = a % b;
|
||||||
|
a = b;
|
||||||
|
b = r;
|
||||||
|
}
|
||||||
|
return (a < 0) ? -a : a;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds minimum resolution Δ given a set of samples which are known to be in the form of N*Δ.
|
||||||
|
// We use GCD of all samples as a simple estimator.
|
||||||
|
function estimateMinimumResolution(samples) {
|
||||||
|
var gcd;
|
||||||
|
for (const sample of samples) {
|
||||||
|
gcd = gcd ? computeGCD(gcd, sample) : sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
const samples = [];
|
||||||
|
for (var i = 0; i < 1e3; i++) {
|
||||||
|
var deltaInMicroSeconds = 0;
|
||||||
|
const e1 = new MouseEvent('test1');
|
||||||
|
do {
|
||||||
|
const e2 = new MouseEvent('test2');
|
||||||
|
deltaInMicroSeconds = Math.round((e2.timeStamp - e1.timeStamp) * 1000);
|
||||||
|
} while (deltaInMicroSeconds == 0) // only collect non-zero samples
|
||||||
|
|
||||||
|
samples.push(deltaInMicroSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
const minResolution = estimateMinimumResolution(samples);
|
||||||
|
assert_greater_than_equal(minResolution, 5);
|
||||||
|
}, 'Event timestamp should not have a resolution better than 5 microseconds');
|
||||||
|
</script>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Event.type set to the empty string</title>
|
||||||
|
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
function do_test(t, e) {
|
||||||
|
assert_equals(e.type, "", "type");
|
||||||
|
assert_equals(e.bubbles, false, "bubbles");
|
||||||
|
assert_equals(e.cancelable, false, "cancelable");
|
||||||
|
|
||||||
|
var target = document.createElement("div");
|
||||||
|
var handled = false;
|
||||||
|
target.addEventListener("", t.step_func(function(e) {
|
||||||
|
handled = true;
|
||||||
|
}));
|
||||||
|
assert_true(target.dispatchEvent(e));
|
||||||
|
assert_true(handled);
|
||||||
|
}
|
||||||
|
|
||||||
|
async_test(function() {
|
||||||
|
var e = document.createEvent("Event");
|
||||||
|
e.initEvent("", false, false);
|
||||||
|
do_test(this, e);
|
||||||
|
this.done();
|
||||||
|
}, "initEvent");
|
||||||
|
|
||||||
|
async_test(function() {
|
||||||
|
var e = new Event("");
|
||||||
|
do_test(this, e);
|
||||||
|
this.done();
|
||||||
|
}, "Constructor");
|
||||||
|
</script>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Event.type</title>
|
||||||
|
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
|
||||||
|
<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
|
||||||
|
<script src="../../resources/testharness.js"></script>
|
||||||
|
<script src="../../resources/testharnessreport.js"></script>
|
||||||
|
<div id="log"></div>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
assert_equals(e.type, "");
|
||||||
|
}, "Event.type should initially be the empty string");
|
||||||
|
test(function() {
|
||||||
|
var e = document.createEvent("Event")
|
||||||
|
e.initEvent("foo", false, false)
|
||||||
|
assert_equals(e.type, "foo")
|
||||||
|
}, "Event.type should be initialized by initEvent");
|
||||||
|
test(function() {
|
||||||
|
var e = new Event("bar")
|
||||||
|
assert_equals(e.type, "bar")
|
||||||
|
}, "Event.type should be initialized by the constructor");
|
||||||
|
</script>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue