b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright<div class="intro">
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright When creating automated tests for your application or modules, you need
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright to be able to mock user events. The DOM supports creating native events
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright that behave essentially the same as user generated events, though
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright without the associated browser default behaviors (e.g. following a link
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright The `event-simulate` module adds the `Y.Event.simulate` method for
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright working with raw DOM nodes, but for most cases, the
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright `node-event-simulate` module is the right choice, since it allows you
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright to call the `simulate` method directly from the `Node`.
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright<h2>Simulating Mouse Events</h2>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright There are seven mouse events that can be simulated:
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <li>`click`</li>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <li>`dblclick`</li>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <li>`mousedown`</li>
a7e9ca67d735ae1bcdc1f7deb35ab98dd9c9f614Derek Gathright <li>`mouseup`</li>
78ac1ef5c64e9e95a94bbfe859662da6d21b243aEric Ferraiuolo <li>`mouseover`</li>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <li>`mouseout`</li>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <li>`mousemove`</li>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Each event is fired by calling <code>simulate()</code> and passing in two
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright arguments: the type of event to fire and an optional object specifying
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright additional information for the event. To simulate a click on the document's
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright body element, for example, the following code can be used:
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek GathrightYUI().use('node-event-simulate', function(Y) {
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Y.one("body").simulate("click");
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright This code simulates a click with all of the default properties on the
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <code>event</code> object. To specify additional information, such as the
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Shift key being down, the second argument must be used and the exact DOM
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright name for the event property specified (there is browser-normalizing logic
78ac1ef5c64e9e95a94bbfe859662da6d21b243aEric Ferraiuolo that translates these into browser-specific properties when necessary):
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek GathrightY.one("body").simulate("click", { shiftKey: true });
f6eaca952977579049a77179dc827c5fc1d6c808Derek Gathright In this updated example, a click event is fired on the document's body
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright while simulating that the Shift key is down.
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright The extra properties to specify vary depending on the event being simulated
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright and are limited to this list:
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <dt>`detail`</dt>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Indicates the number of times a button was clicked (DOM-compliant
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright browsers only).
f6eaca952977579049a77179dc827c5fc1d6c808Derek Gathright <dt>`screenX`, `screenY`</dt>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright Coordinates of the mouse event in relation to the entire screen
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright (DOM-compliant browsers only).
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <dt>`clientX`, `clientY`</dt>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Coordinates of the mouse event in relation to the browser client
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <dt>`ctrlKey`, `altKey`, `shiftKey`, `metaKey`</dt>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright The state of the Ctrl, Alt, Shift, and Meta keys, respectively
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright (true for down, false for up).
78ac1ef5c64e9e95a94bbfe859662da6d21b243aEric Ferraiuolo <dt>`button`</dt>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright The button being used for the event, 0 for left (default), 1 for
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright right, 2 for center.
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <dt>`relatedTarget`</dt>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright the element the mouse moved from (during a `mouseover` event) or to
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright (during a `mouseout` event).
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek GathrightYUI().use('node-event-simulate', function(Y) {
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright var node = Y.one("#myDiv");
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright //simulate a click Alt key down
78ac1ef5c64e9e95a94bbfe859662da6d21b243aEric Ferraiuolo node.simulate("click", { altKey: true});
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a double click with Ctrl key down
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright node.simulate("dblclick", { ctrlKey: true });
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a mouse over
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright node.simulate("mouseover", { relatedTarget: document.body });
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a mouse out
f6eaca952977579049a77179dc827c5fc1d6c808Derek Gathright node.simulate("mouseout", { relatedTarget: document.body });
78ac1ef5c64e9e95a94bbfe859662da6d21b243aEric Ferraiuolo //simulate a mouse down at point (100,100) in the client area
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright node.simulate("mousedown", { clientX: 100, clientY: 100 });
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a mouse up at point (100,100) in the client area
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright node.simulate("mouseup", { clientX: 100, clientY: 100 });
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a mouse move at point (200, 200) in the client area
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright node.simulate("mousemove", { clientX: 200, clientY: 200 });
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright<h2>Simulating Key Events</h2>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright<p>There are three key event simulations available:</p>
a7e9ca67d735ae1bcdc1f7deb35ab98dd9c9f614Derek Gathright <li>`keyup`</li>
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright <li>`keydown`</li>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <li>`keypress`</li>
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright As with the mouse events, key events are simulated using
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <code>simulate()</code>. For <code>keyup</code> and <code>keydown</code>,
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright the <code>keyCode</code> property must be specified; for
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <code>keypress</code>, the <code>charCode</code> property must be included.
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright In many cases, <code>keyCode</code> and <code>charCode</code> may be the
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright same value to represent the same key (97, for instance, represents the
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright "A" key as well as being the ASCII code for the letter
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright "a"). For example:
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek GathrightYUI().use('node-event-simulate', function(Y) {
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright var node = Y.one("#myDiv");
1321f3d57acdabe63869fd24affd5953be3348b7Derek Gathright //simulate a keydown on the A key
1321f3d57acdabe63869fd24affd5953be3348b7Derek Gathright node.simulate("keydown", { keyCode: 97 });
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright //simulate a keyup on the A key
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright node.simulate("keyup", { keyCode: 97 });
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright //simulate typing "a"
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright node.simulate("keypress", { charCode: 97 });
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright Key events also support the <code>ctrlKey</code>, <code>altKey</code>,
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright <code>shiftKey</code>, and <code>metaKey</code> event properties.
1321f3d57acdabe63869fd24affd5953be3348b7Derek Gathright <strong>Note:</strong> Due to differences in browser implementations, key
1321f3d57acdabe63869fd24affd5953be3348b7Derek Gathright events may not be simulated in the same manner across all browsers. For
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright instance, when simulating a keypress event on a textbox, only Firefox will
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright update the textbox with the new character of the key that was simulated to
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright be pressed. For other browsers, the events are still registered and all
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright event handlers are called, however, the textbox display and
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright <code>value</code> property are not updated. These differences should go
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright away as browser support for simulated events improves in the future.
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright<h2>Simulating UI Events</h2>
c3e956d9b62a538911d580547f2dff07b7f0a4b0Derek Gathright<p>There are several UI event simulations available:</p>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright <li>`blur`</li>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright <li>`change`</li>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright <li>`focus`</li>
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright <li>`resize`</li>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright <li>`scroll`</li>
1321f3d57acdabe63869fd24affd5953be3348b7Derek Gathright <li>`select`</li>
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright As with the other events, UI events are simulated using
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright <code>simulate()</code>. There are no properties that are required to
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright simulate UI events as these events don't carry extra information. Some
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek GathrightYUI().use('node-event-simulate', function(Y) {
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright var node = Y.one("#myInput");
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright //simulate a change event
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright //simulate a select event
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright<h2>Caveats and Coming Soons</h2>
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright<h3 id="faking">Don't use simulation in user facing code</h3>
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright Event simulation is for automated testing. Your application should respond
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright to real user events. For reasons
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright <a href="#only-what-you-ask-for">mentioned below</a>, it can be easy to get
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright your application into a confused runtime state when some callbacks have
c3e956d9b62a538911d580547f2dff07b7f0a4b0Derek Gathright been executed but not others.
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright Typically, event simulation is sought to trigger certain callbacks. If a
b2e3e4e5b9ad601bb552e859ade3329168457dd6Derek Gathright function needs to respond to user action or be called programmatically, it
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright should be written accordingly and called directly in the latter case.
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright Often a better solution is to extract the core logic from the event handler
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright into a separate function and call that method from the event handler and
d8a453d703387a8f8168c110b3a052dc60e4a794Derek Gathright from the other part of the application that was going to use simulation.
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright In some cases, simulation is wanted because there may be any number of
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright subscriptions on a node, and all applicable callbacks should be triggered.
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright If this is the case, investigate using <a
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright href="../event-custom/index.html">custom events</a>, instead.
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright The bottom line is, reliance on event simulation in production code is a
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright warning sign that the architecture is not scaling. The affected code
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright should be refactored before it becomes a larger problem.
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright<h3>Only what you ask for</h3>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright In many cases, events happen in groups (`mousedown`, `mouseup`, `click`, or
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright `keydown`, `keyup`, `keypress`). If you simulate an event that is
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright typically part of a group or is often followed by other events, <em>the
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright other events will NOT be generated</em> for free.
c3e956d9b62a538911d580547f2dff07b7f0a4b0Derek Gathright For example, if you simulate a `click` event on a submit button, you only
c3e956d9b62a538911d580547f2dff07b7f0a4b0Derek Gathright simulate the `click` event. The preceding `mousedown` and `mouseup`, as
c3e956d9b62a538911d580547f2dff07b7f0a4b0Derek Gathright well as the subsequently expected 'submit' are neither simulated or fired
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright<h3>No touch events yet</h3>
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright Currently, there's no support for simulating touch events or other events
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright not noted explicitly above.
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright<h3>No synthetic event simulation yet</h3>
bb09a8bcec28d3fcfe6649ea17c5042b68ea1627Derek Gathright The <a href="synths.html">Synthetic event system</a> doesn't yet support
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright defining simulation. In most cases, though, synthetic events are triggered
615e6a4633b53af433f9bfb616363b682d487043Derek Gathright by other DOM events that can be simulated, so it's often possible to
8d2276a4a406c3a9565c3950d2bec8831f3bb6d9Derek Gathright trigger them by simulating the underlying events. But that ignores the
8d2276a4a406c3a9565c3950d2bec8831f3bb6d9Derek Gathright point that synthetic events are supposed to mask that abstraction for your
e592b34ac3f93557b9c7b30f9debc810a4875e79Derek Gathright Support for synthetic event simulation is on the roadmap.