Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing angular mousedown, mousemove, mouseup

In the directives section of the angular docs

They provide roughly this example of how to make a drag thing.

My question is how would you test THEIR EXAMPLE/implementation:

  var startX = 0, startY = 0;
  scope.x = 0;
  scope.y = 0;
  element.css({
    top: scope.y, 
    left: scope.x
  });

  element.on('mousedown', function(event) {
    // Prevent default dragging of selected content
    event.preventDefault();
    startX = event.pageX - scope.x;
    startY = event.pageY - scope.y;
    $document.on('mousemove', mousemove);
    $document.on('mouseup', mouseup);
  });

  function mousemove(event) {
    scope.y = event.pageY - startY;
    scope.x = event.pageX - startX;
    element.css({
      top: scope.y + 'px',
      left: scope.x + 'px'
    });
  }

  function mouseup() {
    $document.off('mousemove', mousemove);
    $document.off('mouseup', mouseup);
  }
}

but that only works for a single event.

Angular's example uses the mousedown to add the mousemove and mouseup event listeners, and this stackoverflow answer uses triggerHandler-- which prevents bubbling/propagation.

right now i have (roughly):

describe('on mousedown it', function(){
  it('moves a thing', function(){
    expect(scope.x).toBe(0);
    element.triggerHandler({type: 'mousedown', pageX: 0, pageY:0});
    element.triggerHandler({type: 'mousemove', pageX:10, pageY:10);
    expect(scope.x).toBe(10);
  });
});

test is failing. scope.x is logging as 0. what do?

like image 719
Andrew Luhring Avatar asked Jun 16 '16 17:06

Andrew Luhring


People also ask

What is Mousedown and MouseUp?

MouseDown occurs when the user presses the mouse button; MouseUp occurs when the user releases the mouse button.

How do you trigger event in Jasmine?

According to the Angular Testing documentation, to trigger the events from the tests, we use the triggerEventHandler() method on the debug element. This method takes the event name and the object . Now, this works if we are adding the events using the HostListener .

What is Mousedown in angular?

Definition and Usage. The ng-mousedown directive tells AngularJS what to do when a mouse button is clicked on the specific HTML element. The ng-mousedown directive from AngularJS will not override the element's original onmousedown event, both will be executed.


2 Answers

Ok the way I look at this, in the example, the dragging code is in a directive. So, when looking at testing, because the directive is manipulating the position of the element that the directive is attached to, I would assert the changes in element position rather than asserting values of internal scope variables.

Given we have the directive called myDraggable which is applied like so <span my-draggable="">Drag Me</span>, when testing:

  1. Lets compile the directive.

    var scope = $rootScope.$new(); var elem = $compile('<span my-draggable="">Drag Me</span>')(scope);

  2. Then send mouse down event to compiled element

    elem.triggerHandler({type: 'mousedown', pageX: 0, pageY:0});

  3. After that, because the mouse move event is attached to the $document, lets send mouse mouse move event to $document

    $document.triggerHandler({type: 'mousemove', pageX: 10, pageY:20});

  4. And finally, let's assert the final position of the compiled element

    expect(elem.css('top')).toBe('20px') expect(elem.css('left')).toBe('10px')

And when we put it all together,

describe('on mousedown it', function(){
  beforeEach(module('dragModule'));

  it('moves a thing', inject(function($compile, $rootScope, $document){
    var scope = $rootScope.$new();
    var elem = $compile('<span my-draggable="">Drag Me</span>')(scope);
    $rootScope.$digest();

    elem.triggerHandler({type: 'mousedown', pageX: 0, pageY:0});
    $document.triggerHandler({type: 'mousemove', pageX: 10, pageY:20});

    expect(elem.css('top')).toBe('20px');
    expect(elem.css('left')).toBe('10px');
  }));
});

Here's official angular documentation on recommended way of testing a directive: https://docs.angularjs.org/guide/unit-testing#testing-directives

Here's the plunker that implements everything I just talked about: https://plnkr.co/edit/QgWiVlbNOKkhn6wkGxUK?p=preview

like image 92
Chanthu Avatar answered Nov 16 '22 22:11

Chanthu


You can test/assert for scope.x also , but do consider above answer by Chanthu - the way to compile directive with a scope.

Besides that ,the reason why your test fails is all events except mousedown are triggered on document unlike your test case depicts.

Try following snippet:

                       describe('on mousedown it', function(){
                        it('moves a thing', function(){
                         expect(scope.x).toBe(0);
                         element.triggerHandler({type: 'mousedown',           
                         pageX: 0, pageY:0});
                         document.triggerHandler({type: 'mousemove', 
                         pageX:10, pageY:10);
                         expect(scope.x).toBe(10);
                        });
                      });
like image 32
adiinstack Avatar answered Nov 16 '22 21:11

adiinstack