问题
I want to use TestUtils.Simulate.mouseMove
on the document
. I have a component Dragger
that adds a mouseMove
event listener to the document
. Here is an incomplete version:
// Dragger.js
'use strict';
var React = require('react');
export default React.createClass({
propTypes: {
handleDrag: React.PropTypes.func // callback set by parent
},
getInitialState: function() {
return {dragging: false}
},
componentDidUpdate: function(props, state) {
//
if (this.state.dragging && !state.dragging) {
document.addEventListener('mousemove', this.onMouseMove)
} else if (!this.state.dragging && state.dragging) {
document.removeEventListener('mousemove', this.onMouseMove)
}
},
onMouseDown: function(e) {
this.setState({dragging: true})
},
onMouseMove: function(e) {
// Calls back to the parent with the drag
this.props.handleDrag(e);
},
render: function() {
return <div onMouseDown={this.onMouseDown} ></div>
}
});
I'm using jasmine, and I want to make sure my handleDrag
callback is called after a mouseDown
followed by a mouseMove
.
// Dragger.spec.js
var React = require('react/addons');
import Dragger from './Dragger';
var TestUtils = React.addons.TestUtils;
describe('Dragger', function() {
it('should call the callback after drag interaction', function() {
// make callback to spy on
var f = {callback: function(e){return}};
// render Dragger
var dragger = TestUtils.renderIntoDocument(<Dragger handleDrag={f.callback} />);
// spy on callback
spyOn(f, 'callback');
// simulate a mouseDown and mouseMove
TestUtils.Simulate.mouseDown(dragger.getDOMNode(), {button: 0});
TestUtils.Simulate.mouseMove(document);
expect(f.callback).toHaveBeenCalled(); // FAILS!
}
}
But the mouseMove
event is not being properly simulated. I see 2 problems
- I might need to pass event data to
TestUtils.Simulate.mouseMove
. For example, the callTestUtils.Simulate.mouseDown(dragger.getDOMNode())
did not work until I changed it toTestUtils.Simulate.mouseDown(dragger.getDOMNode(), {button: 0})
. What event data should I pass toTestUtils.Simulate.mouseMove
? - The
document
is not part of the detached DOM that the test component is rendered into. This could be another reason theSimulate.mouseMove
doesn't work. What can I use in the test instead ofdocument
?
How can I use TestUtils.Simulate.mouseMove
?
回答1:
After hours of trying various methods with enzyme and react's TestUtils I finally came upon just creating and dispatching events in pure JS, which works in my jest tests like this
it('calls handler on mouseDown on element, mouseMove on document', () => {
const handler = jest.fn();
const props = {
foo: {
uid: '1',
resizable: true,
},
resizeHandler,
};
const instance = mount(<Header {...props} />);
const resizer = instance.find('.resizer');
const top = window.document.documentElement; // target the documentElement
resizer.simulate('mouseDown', { preventDefault: () => true }); // uses enzyme to simulate this event, adding listener to documentElement on mousemove
const mouseMove = new Event('mousemove'); // creates a new event
top.dispatchEvent(mouseMove); // dispatches it
const mouseUp = new Event('mouseup');
top.dispatchEvent(mouseUp);
expect(resizeHandler).toBeCalled(); // the passed in handler is called on mousemove
});
Basically, you can find document.documentElement
with window.document.documentElement
and dispatch events from it like any other element
回答2:
This is an old post but I see there isn't a posted solution yet, I run into it because I am writing a similar component. I think the problem is that you are focusing on the wrong event, you should be using onDrag
for dragging detection, here's an adapted version of your code that is working for me:
// Dragger.js
import React from 'react';
export default React.createClass({
propTypes: {
handleDrag: React.PropTypes.func // callback set by parent
},
getInitialState: function() {
return {dragging: false}
},
onDragStart: function(e) {
// Calls back to the parent with the drag
this.setState({ dragging: true });
this.props.handleDrag(e);
},
onDragEnd: function() {
this.setState({ dragging: false });
},
render: function() {
return <div onDragStart={this.onDragStart} onDragEnd={this.onDragEnd}></div>;
}
});
and
// Dragger.spec.js
import React from 'react';
import Dragger from '../src/Dragger';
import {
renderIntoDocument,
scryRenderedDOMComponentsWithTag,
Simulate
} from 'react-addons-test-utils';
import { expect } from 'chai';
describe('Dragger', function() {
it('should call the callback after drag interaction', function() {
// spy on callback
var called = false;
// make callback to spy on
function callback() {
called = true;
};
// render Dragger
var dragger = renderIntoDocument(<Dragger handleDrag={callback} />);
// simulate a dragStart and dragEnd
const element = scryRenderedDOMComponentsWithTag(dragger, 'div')[0];
Simulate.dragStart(element);
Simulate.dragEnd(element);
expect(called).to.equal(true);
});
});
来源:https://stackoverflow.com/questions/31055738/react-testutils-how-can-i-simulate-document-mousemove