Reputation: 1894
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?
Upvotes: 7
Views: 3695
Reputation: 96
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);
});
});
Upvotes: 2
Reputation: 1794
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:
Lets compile the directive.
var scope = $rootScope.$new();
var elem = $compile('<span my-draggable="">Drag Me</span>')(scope);
Then send mouse down event to compiled element
elem.triggerHandler({type: 'mousedown', pageX: 0, pageY:0});
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});
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
Upvotes: 4