Add CommandRegistry::dispatch for tests

This commit is contained in:
Nathan Sobo
2014-09-17 19:03:52 -06:00
parent cf4a7c22ee
commit 0c9fd46030
2 changed files with 61 additions and 32 deletions

View File

@@ -124,3 +124,17 @@ describe "CommandRegistry", ->
{name: 'namespace:command-2', displayName: 'Namespace: Command 2'}
{name: 'namespace:command-1', displayName: 'Namespace: Command 1'}
]
describe "::dispatch(target, commandName)", ->
it "simulates invocation of the given command ", ->
called = false
registry.add '.grandchild', 'command', (event) ->
expect(this).toBe grandchild
expect(event.type).toBe 'command'
expect(event.eventPhase).toBe Event.BUBBLING_PHASE
expect(event.target).toBe grandchild
expect(event.currentTarget).toBe grandchild
called = true
registry.dispatch(grandchild, 'command')
expect(called).toBe true

View File

@@ -51,8 +51,8 @@ class CommandRegistry
@rootNode = newRootNode
for commandName of @listenersByCommandName
oldRootNode?.removeEventListener(commandName, @dispatchCommand, true)
newRootNode?.addEventListener(commandName, @dispatchCommand, true)
oldRootNode?.removeEventListener(commandName, @handleCommandEvent, true)
newRootNode?.addEventListener(commandName, @handleCommandEvent, true)
# Public: Add one or more command listeners associated with a selector.
#
@@ -88,7 +88,7 @@ class CommandRegistry
return disposable
unless @listenersByCommandName[commandName]?
@rootNode?.addEventListener(commandName, @dispatchCommand, true)
@rootNode?.addEventListener(commandName, @handleCommandEvent, true)
@listenersByCommandName[commandName] = []
listener = new CommandListener(selector, callback)
@@ -99,35 +99,7 @@ class CommandRegistry
listenersForCommand.splice(listenersForCommand.indexOf(listener), 1)
if listenersForCommand.length is 0
delete @listenersByCommandName[commandName]
@rootNode.removeEventListener(commandName, @dispatchCommand, true)
dispatchCommand: (event) =>
propagationStopped = false
immediatePropagationStopped = false
currentTarget = event.target
syntheticEvent = Object.create event,
eventPhase: value: Event.BUBBLING_PHASE
currentTarget: get: -> currentTarget
stopPropagation: value: ->
propagationStopped = true
stopImmediatePropagation: value: ->
propagationStopped = true
immediatePropagationStopped = true
loop
matchingListeners =
@listenersByCommandName[event.type]
.filter (listener) -> currentTarget.webkitMatchesSelector(listener.selector)
.sort (a, b) -> a.compare(b)
for listener in matchingListeners
break if immediatePropagationStopped
listener.callback.call(currentTarget, syntheticEvent)
break if propagationStopped
break if currentTarget is @rootNode
currentTarget = currentTarget.parentNode
@rootNode.removeEventListener(commandName, @handleCommandEvent, true)
# Public: Find all registered commands matching a query.
#
@@ -163,6 +135,49 @@ class CommandRegistry
commands
# Public: Simulate the dispatch of a command on a DOM node.
#
# This can be useful for testing when you want to simulate the invocation of a
# command on a detached DOM node. Otherwise, the DOM node in question needs to
# be attached to the document so the event bubbles up to the root node to be
# processed.
#
# * `target` The DOM node at which to start bubbling the command event.
# * `commandName` {String} indicating the name of the command to dispatch.
dispatch: (target, commandName) ->
event = new CustomEvent(commandName, bubbles: true)
eventWithTarget = Object.create(event, target: value: target)
@handleCommandEvent(eventWithTarget)
handleCommandEvent: (event) =>
propagationStopped = false
immediatePropagationStopped = false
currentTarget = event.target
syntheticEvent = Object.create event,
eventPhase: value: Event.BUBBLING_PHASE
currentTarget: get: -> currentTarget
stopPropagation: value: ->
propagationStopped = true
stopImmediatePropagation: value: ->
propagationStopped = true
immediatePropagationStopped = true
loop
matchingListeners =
@listenersByCommandName[event.type]
.filter (listener) -> currentTarget.webkitMatchesSelector(listener.selector)
.sort (a, b) -> a.compare(b)
for listener in matchingListeners
break if immediatePropagationStopped
listener.callback.call(currentTarget, syntheticEvent)
break unless currentTarget?
break if currentTarget is @rootNode
break if propagationStopped
currentTarget = currentTarget.parentNode
clear: ->
@listenersByCommandName = {}