mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +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: https://github.com/LadybirdBrowser/ladybird/commit/aa9ed71ff34 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…
Reference in a new issue