使用 React testutils 模拟拖放不起作用

Simulating drag drop with react testutils not working

我正在尝试使用 jasmine、karma 和 React TestUtils 测试我的 ReactJS mixin 的拖放功能。

没有抛出异常,但是调试的时候好像模拟事件的时候绑定到事件监听器的函数没有被执行。

您可以在此处克隆它: https://github.com/itsh01/react-dragdrop/tree/testing-simutale-events

非常感谢您。

这是我的测试:

beforeEach(function () {

    var CompDrag = React.createClass({
        mixins: [DragDropMixin],
        dragDrop: function dragDrop() {
            return {
                draggable: true,
                dropType: 'test',
                dataTransfer: {
                    test: true
                }
            };
        },
        render: function render() {
            return React.createElement('div', {});
        }
    });

    var CompDrop = React.createClass({
        mixins: [DragDropMixin],
        dragDrop: function dragDrop() {
            var self = this;
            return {
                droppable: true,
                acceptableTypes: ['test'],
                drop: function (data) {
                    self.setState(data);
                }
            };
        },
        render: function render() {
            return React.createElement('div', {});
        }
    });

    elementDrag = React.createElement(CompDrag, {});
    elementDrop = React.createElement(CompDrop, {});

});

...

it('should attach drop functionality when configured', function () {
    var renderedDrag = TestUtils.renderIntoDocument(elementDrag);
    var renderedDrop = TestUtils.renderIntoDocument(elementDrop);
    var nodeDrag = renderedDrag.getDOMNode();
    var nodeDrop = renderedDrop.getDOMNode();
    var mockEvent = {
        preventDefault: function () {},
        dataTransfer: {
            types: ["objtopass"],
            setData: function () {},
            getData: function () {
                return JSON.parse({
                    dropType: 'test',
                    data: {
                        test: true
                    }
                });
            }
        }
    };

    TestUtils.SimulateNative.dragStart(nodeDrag, mockEvent);
    TestUtils.Simulate.dragOver(nodeDrop, mockEvent);
    TestUtils.Simulate.drop(nodeDrop, mockEvent);

    expect(renderedDrop.state).not.toBeNull();
});

这是混音:

'use strict';

var _ = lodash;

var DragDropMixin = {
    /*
     *  usage:
     *
     *  mixins: [DragDropMixin],
     *  dragDrop: function () {
     *
     *     return {
     *
     *         // when dragging an item
     *         draggable: true,
     *         dropType: 'myItem',
     *         dataTransfer: { myItemData: property }
     *
     *         // when dropping an item:
     *         droppable: true,
     *         acceptableDrops: ['myItem'],
     *         drop: function (myItem) {},
     *     };
     *  }
     *
     */
    isAttrEnabled: function (attr) {
        return this.dragDropData && this.dragDropData[attr];
    },
    isDroppable: function () {
        return this.isAttrEnabled('droppable');
    },
    isDraggable: function () {
        return this.isAttrEnabled('draggable');
    },
    componentDidMount: function () {
        var node = this.getDOMNode();

        this.dragDropData = this.dragDrop();

        if (this.isDroppable()) {
            node.addEventListener('dragover', this.handleDragOver, this);
            node.addEventListener('drop', this.handleDrop, this);
        }

        if (this.isDraggable()) {
            node.draggable = true;
            node.addEventListener('dragstart', this.handleDragStart, this);
        }
    },
    componentWillUnmount: function () {
        var node = this.getDOMNode();

        if (this.isDroppable()) {
            node.removeEventListener('dragover', this.handleDragOver);
            node.removeEventListener('drop', this.handleDrop);
        }

        if (this.isDraggable()) {
            node.removeEventListener('dragstart', this.handleDragStart);
        }
    },
    handleDragOver: function (e) {
        e.preventDefault();
    },
    handleDrop: function (e) {
        var jsonData = e.dataTransfer.getData('objToPass'),
            passedObj = JSON.parse(jsonData),
            acceptableDrops = this.dragDropData.acceptableDrops;

        e.preventDefault();

        if (!this.dragDropData.drop) {
            throw new Error('Must define drop function when using droppable');
        }

        if (_.includes(acceptableDrops, passedObj.dropType)) {
            this.dragDropData.drop(passedObj.data);
        }

    },
    handleDragStart: function (e) {
        var objToPass = {
            data: this.dragDropData.dataTransfer,
            dropType: this.dragDropData.dropType
        };

        e.dataTransfer.setData('objToPass', JSON.stringify(objToPass));
    }
};

再次感谢。

好的,明白了。

我其实是在监听原生事件,模拟React合成事件。

通过更改 mixin 修复了它:

componentDidMount: function () {
    var node = this.getDOMNode();

    this.dragDropData = this.dragDrop();

    if (this.isDroppable()) {
        node.ondragover = this.handleDragOver;
        node.ondrop = this.handleDrop;
    }

    if (this.isDraggable()) {
        node.draggable = true;
        node.ondragstart = this.handleDragStart;
    }
},

并通过触发原生事件进行测试

    nodeDrag.ondragstart(mockEvent);
    nodeDrop.ondragover(mockEvent);
    nodeDrop.ondrop(mockEvent);

    expect(DragDropMixin.handleDrop).toHaveBeenCalled();
    expect(renderedDrop.state).toBeNull();