Reputation: 7235
I have a chart directive in my angular application that makes use of the d3.js library.
Part of the directive adds mouse event handlers to some svg elements like so
svg.selectAll('g rect')
.on('click', function(d) {
scope.clickHandler(d, scope.data);
})
.on('mouseover', function () {
d3.select(this).classed('data-item-hover', true);
})
.on('mouseout', function () {
d3.select(this).classed('data-item-hover', false);
});
I want to cover these handlers in some unit tests, but am struggling with how to actually invoke these events dynamically.
I am attempting this in my test spec
describe('scope.clickHandler', function() {
var rect;
beforeEach(function(){
spyOn(scope, 'clickHandler');
rect = svg.select('g rect')[0][0];
rect.on('click')();
});
it('should call scope.render after a window resize event occurs', function () {
expect(scope.clickHandler).toHaveBeenCalled();
});
});
However this throws an error
TypeError: undefined is not a constructor (evaluating 'rect.on('click')'
I came across this SO How to invoke "click" event programmatically in d3? and the second answer is what has led me to trying this technique.
How can I call a mouse event on the svg elements that I have registered events with in d3.js?
Thanks
Upvotes: 2
Views: 2433
Reputation: 4427
The main issue is that svg.select('g rect')[0][0]
is a DOM element and not a proper D3 selection, that's why you get undefined
error. From the docs:
Selections are arrays of elements—literally (maybe not literally...). D3 binds additional methods to the array so that you can apply operators to the selected elements...
You can actually check that since a DOM element implements the Element
interface:
(svg.select('g rect')[0][0] instanceof Element) // true
So in order to trigger some event on a certain element, you could do the following:
var rect = svg.select('g rect') // first rect element found is assumed
rect.on('click').call(rect.node(), rect.datum()); // as commented in above link
You can find a simple working fiddle here.
Upvotes: 4