Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass mock DOM event to directive handler without jQuery

I have a very simple directive whose purpose is just to cancel the dragstart event:

link: function(scope, element) {
  element.on('dragstart', function(e) {
    e.preventDefault();
  })
}

How can I test this in a Jasmine test? I have the following test that attempts to spy on an Event object, and pass it to the handler:

var mockEvent; 

beforeEach(function() {
  mockEvent = new Event('dragstart');
  spyOn(mockEvent,'preventDefault');
});

it('should call preventDefault', function () {
  element.triggerHandler('dragstart', mockEvent);
  expect(mockEvent.preventDefault).toHaveBeenCalled();
});

But the test fails. You can see this at this Plunker.. How can I test this (/refactor the directive to make it testable)?

Edit: Ideally without including jQuery. Edit: changed tags

like image 555
Michal Charemza Avatar asked Jan 07 '14 08:01

Michal Charemza


2 Answers

you may include jquery and create a jquery event object. this object can easly be passed:

beforeEach(function() {
  mockEvent = $.Event('dragstart');
  spyOn(mockEvent,'preventDefault');
});

it('should call preventDefault', function () {
  element.triggerHandler(mockEvent);
  expect(mockEvent.preventDefault).toHaveBeenCalled();
});

i have used this jquery version in your plunkr: //ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js

like image 139
michael Avatar answered Oct 14 '22 15:10

michael


At the current stable version of Angular, 1.3.14, you can do this without jQuery by passing the event as the first and only parameter of triggerHandler, so instead of what was suggested in the question

element.triggerHandler('dragstart', new Event('dragstart'));

you can write

element.triggerHandler(new Event('dragstart'));

To add a spy on the preventDefault function, as per the original question, you can do the following

var mockEvent; 

beforeEach(function() {
  mockEvent = new Event('dragstart');
  spyOn(mockEvent, 'preventDefault');
});

it('should call preventDefault', function () {
  element.triggerHandler(mockEvent);
  expect(mockEvent.preventDefault).toHaveBeenCalled();
});

You can see this working in this Plunker. You can alternatively just use a plain object with at least a type key, so in this case

mockEvent = {
  type: 'dragstart',
  preventDefault: jasmine.createSpy('preventdefault')
};

which can be seen working in this Plunker

I believe this was added to the 1.3 branch in this commit.

like image 40
Michal Charemza Avatar answered Oct 14 '22 17:10

Michal Charemza