velesin / jasmine-jquery

jQuery matchers and fixture loader for Jasmine framework
MIT License
1.89k stars 347 forks source link

toHandle doesn't support delegated .on() syntax #145

Open nzifnab opened 11 years ago

nzifnab commented 11 years ago

As the title suggests, when you bind an event using this syntax:

$('.my-parent-element').on('click', '.child-element', function(e){
  // Do cool things
});

This doesn't work:

expect($(".child-element")).toHandle('click')

But this does:

expect($(".my-parent-element")).toHandle('click')

Event though it's not actually clicking that parent element that causes the function to run. I would almost expect some kind of method like

expect($(".child-element")).toHandleFromDelegation('click')

or something. I saw this: https://github.com/velesin/jasmine-jquery/pull/40 but it was written for deprecated delegation syntax and closed quite some time ago. Is there a matcher I can use to work-around this issue and test that the child element has the handler on it? I'm not sure if it's a bug that toHandle fails on the child selector, but if it is I can produce a test case if needed.

bradgreens commented 11 years ago

:+1:

agreco commented 10 years ago

is this issue being considered?

isaachvazquez commented 8 years ago

👍

erlandsona commented 8 years ago

👍 What's the status on this one?

Jefferson-Faseler commented 6 years ago

I ran into this problem with some code and didn't find a solution so I made a custom matcher that will just recursively travel up the DOM. It's pretty limited to my own use case so it won't receive a handler function option, but this works until the issue is resolved.

beforeEach(function () {
  jasmine.addMatchers({
    toHandleThroughDelegation: function () {
      return {
        compare: function (actual, expected) {
          var selector = actual.selector
          var eventType = expected
          var delegatesEvent = findEventHandlerDelegate($(selector).slice(0,1).parent(), selector, eventType)
          return {
            pass: delegatesEvent === true
          }
        }
      }
    }
  });
});

function findEventHandlerDelegate(element, selector, eventType) {
  var delegatedData, eventTypeHandlers, doesDelegate
  var eventHandlers = $._data( $(element)[0], 'events' )
  if (eventHandlers) {
    eventTypeHandlers = eventHandlers[eventType]
    if (eventTypeHandlers) {
      delegatedData = eventTypeHandlers.filter(function(handler) {
        return handler.selector === selector
      })
      if (delegatedData[0]) {
        doesDelegate = delegatedData[0].selector === selector
      }
    }
  }
  if ($(element).is(document) || doesDelegate) {
    return doesDelegate
  }
  return findEventHandlerDelegate($(element).parent(), selector, eventType)
}
Jefferson-Faseler commented 6 years ago

Another weird problem we have hit is that anything delegated to document won't be removed between tests. Another issue you may encounter when testing delegated events.