【问题标题】:React TestUtils, how can I simulate document mouseMove?React TestUtils,如何模拟文档mouseMove?
【发布时间】:2015-09-12 09:04:32
【问题描述】:

我想在document 上使用TestUtils.Simulate.mouseMove。我有一个组件Dragger,它将mouseMove 事件侦听器添加到document。这是一个不完整的版本:

// 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>
    }
});

我正在使用jasmine,并且我想确保在mouseDown 后跟mouseMove 之后调用我的handleDrag 回调。

// 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!
    }
}

但是mouseMove 事件没有被正确模拟。我看到了 2 个问题

  1. 我可能需要将事件数据传递给TestUtils.Simulate.mouseMove。例如,调用 TestUtils.Simulate.mouseDown(dragger.getDOMNode()) 在我将其更改为 TestUtils.Simulate.mouseDown(dragger.getDOMNode(), {button: 0}) 之前不起作用。我应该将哪些事件数据传递给TestUtils.Simulate.mouseMove?
  2. document 不是测试组件渲染到的detached DOM 的一部分。这可能是Simulate.mouseMove 不起作用的另一个原因。我可以在测试中使用什么来代替 document?

如何使用TestUtils.Simulate.mouseMove?

【问题讨论】:

  • 解决你的#2:你是对的,它肯定不会通过传递文档来工作,因为 TestUtils 将你的组件呈现为一个分离的 DOM 节点。我看到你使用的是 Jasmine,所以你可能想看看这个:github.com/tommyh/jasmine-react 它提供了jasmineReact.render,它实际上将组件渲染到一个附加的 DOM 节点中,然后为你清理它。虽然可能有几个问题导致您的代码无法工作,但我相信这至少可以解决其中一个问题
  • 就使用 TestUtils 模拟 mousemove 事件而言,您可能希望尝试在组件上传递您期望的相同信息。我最近与TestUtils.Simulate.keyDown 有类似的问题,因为我使用(不正确的)文档并提供key 而不是keyDown,这是我的代码所期望的。这告诉我,您可以提供几乎任何类型的假数据作为 Simulate.keyDown 的参数(在您的情况下为 mouseMove),它会接受它。

标签: reactjs reactjs-testutils


【解决方案1】:

这是一篇旧帖子,但我发现还没有发布的解决方案,我遇到了它,因为我正在编写一个类似的组件。我认为问题在于您关注的是错误的事件,您应该使用onDrag 进行拖动检测,这是适用于我的代码的改编版本:

// 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>;
    }
});

和

// 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);
    });
});

【讨论】:

    【解决方案2】:

    在用酶和反应的 TestUtils 尝试各种方法数小时后,我终于发现在纯 JS 中创建和调度事件,这在我这样的笑话测试中起作用

    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
    });
    

    基本上,您可以找到document.documentElement 和window.document.documentElement,并像其他任何element 一样从中调度事件

    【讨论】:

    • 你是如何导入事件的?
    猜你喜欢
    • 1970-01-01
    • 2016-08-13
    • 2015-11-09
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 2011-08-25
    相关资源
    最近更新 更多